Ruby 使用 instance_eval 对象初始化
Ruby object initialization using instance_eval
考虑以下 class:
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,而不是直接使用属性。这能做到吗?
试试这个:
person = Person.new do |obj|
obj.first_name = "Adam"
end
puts person.first_name
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
如果代码 运行 启用了警告(即 ruby -w yourprogram.rb
)
它响应:"warning: assigned but unused variable - first_name",line-number 指向 first_name = "Adam"
。所以 Ruby 将 first_name
解释为变量,而不是方法。正如其他人所说,使用显式接收者:self.first_name
.
I want to use the attr_accessor in the initialization block, and not the attributes directly
instance_eval
破坏封装。它使块可以访问实例变量和私有方法。
考虑将人物实例传递到块中:
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">
考虑以下 class:
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,而不是直接使用属性。这能做到吗?
试试这个:
person = Person.new do |obj|
obj.first_name = "Adam"
end
puts person.first_name
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
如果代码 运行 启用了警告(即 ruby -w yourprogram.rb
)
它响应:"warning: assigned but unused variable - first_name",line-number 指向 first_name = "Adam"
。所以 Ruby 将 first_name
解释为变量,而不是方法。正如其他人所说,使用显式接收者:self.first_name
.
I want to use the attr_accessor in the initialization block, and not the attributes directly
instance_eval
破坏封装。它使块可以访问实例变量和私有方法。
考虑将人物实例传递到块中:
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">