Ruby attr_reader允许使用<;修改字符串变量&书信电报;
遇到了一些奇怪的行为,想知道是否有人能证实我所看到的 假设您使用成员变量创建了一个类,并允许使用attr_reader读取该类Ruby attr_reader允许使用<;修改字符串变量&书信电报;,ruby,instance-variables,Ruby,Instance Variables,遇到了一些奇怪的行为,想知道是否有人能证实我所看到的 假设您使用成员变量创建了一个类,并允许使用attr_reader读取该类 class TestClass attr_reader :val def initialize(value) @val = value end end 现在,当我执行以下操作时,它似乎修改了@val的值,尽管我只授予它读取权限 test = TestClass.new('hello') puts test.val test.val <<
class TestClass
attr_reader :val
def initialize(value)
@val = value
end
end
现在,当我执行以下操作时,它似乎修改了@val的值,尽管我只授予它读取权限
test = TestClass.new('hello')
puts test.val
test.val << ' world'
puts test.val
这只是我在irb中进行的一些测试的结果,因此不确定是否总是这样您并不是在真正编写val属性。您正在阅读它并在其上调用一个方法(“只是对您的示例进行了一点修改:
test = TestClass.new([])
现在您应该获得(用p替换put以获得内部视图):
这是一样的。你“读取”val,现在你可以用它做一些事情。在我的例子中,你向数组中添加了一些东西,在你的例子中,你向字符串中添加了一些东西
读访问读取对象(可以修改),写访问更改属性(替换属性)
也许你在寻找冻结:
class TestClass
attr_reader :val
def initialize(value)
@val = value
@val.freeze
end
end
test = TestClass.new('hello')
puts test.val
test.val << ' world'
puts test.val
虽然这似乎出乎意料,但这是完全正确的。让我解释一下
类宏方法定义实例变量的“getter”和“setter”方法
如果没有“getter”方法,您就无法访问对象的实例变量,因为您不在该对象的上下文中
def variable=(value)
@variable = value
end
由于实例变量指向一个具有一组方法本身的可变对象,如果您“获取”它并对其进行操作,则这些更改将发生。您不需要使用上述setter方法调用
变量。赋值与修改不同,变量与对象不同
test.val = "hello world"
将是赋值给@val
实例变量的情况(该变量不起作用),而
test.valattr\u reader
表示您无法设置值,即未定义任何方法value=
。这当然并不意味着您无法在对象上调用方法。请小心操作。您会希望复制该值,这样您就不会冻结其他人传入的变量。@JayMitchellI扩展了我的回答以捕获此副作用。感谢您的提示。您也可以在initialize
中复制并冻结值,而不是实现另一种方法。例如,@val=value.dup.freeze
(如果您知道value
是一个字符串,您可以使用@val=-value
完成相同的操作)
__temp.rb:12:in `<main>': can't modify frozen string (RuntimeError)
hello
class TestClass
attr_reader :val
def initialize(value)
@val = value.dup.freeze #dup to avoid to freeze the variable "value"
end
end
hello = 'hello'
test = TestClass.new(hello)
puts test.val
hello << ' world' #this is possible
puts test.val #this value is unchanged
test.val << ' world' #this is not possible
puts test.val
def variable=(value)
@variable = value
end
test.val = "hello world"
test.val << " world"