考虑以下课程:
class Person
attr_accessor :first_name
def initialize(&block)
instance_eval(&block) if block_given?
end
end
当我按如下方式创建Person的实例时:
person = Person.new do
first_name = "Adam"
end
我期待以下内容:
puts person.first_name
输出" Adam"。相反,它只输出一个空行:first_name属性最终的值为nil。
当我创建一个喜欢这个的人时,不过:
person = Person.new do
@first_name = "Adam"
end
first_name属性设置为期望值。
问题是我想在初始化块中使用attr_accessor,而不是直接使用属性。可以这样做吗?
答案 0 :(得分:3)
如果代码在启用警告的情况下运行(即ruby -w yourprogram.rb
)
它响应:"警告:已分配但未使用的变量 - first_name",其中行号指向first_name = "Adam"
。所以Ruby将first_name
解释为变量,而不是方法。正如其他人所说,使用明确的接收者:self.first_name
。
答案 1 :(得分:2)
如果没有显式接收器,则无法调用Ruby setter,因为局部变量优先于方法调用。
您不需要尝试这样一个过于复杂的示例,以下内容也不会起作用:
class Person
attr_accessor :name
def set_name(new_name)
name = new_name
end
end
只会这样:
class Person
attr_accessor :name
def set_name(new_name)
# name = new_name does not call `#name=`
self.name = new_name
end
end
对于您的示例,您必须在接收器上显式调用该方法:
person = Person.new do
self.first_name = "Adam"
end
答案 2 :(得分:0)
试试这个:
person = Person.new do |obj|
obj.first_name = "Adam"
end
puts person.first_name
答案 3 :(得分:0)
我想在初始化块中使用attr_accessor,而不是直接使用属性
instance_eval
破坏了封装。它为块提供了对实例变量和私有方法的访问。
考虑将person实例传递到块中:
class Person
attr_accessor :first_name
def initialize
yield(self) if block_given?
end
end
用法:
adam = Person.new do |p|
p.first_name = 'Adam'
end
#=> #<Person:0x00007fb46d093bb0 @first_name="Adam">