我有以下代码:
class Dog
def initialize(attributes = {})
attributes.each do |attr, value|
send("#{attr}", value)
end
end
end
dog = Dog.new({:talk => 'bruuuf'})
我在初始化'得到一个块':未定义的方法`talk'for#(NoMethodError)
不发送应该做的事情:
dog.talk = bruuuf
为什么不让我这样做?此外,这不会设置实例变量,但会创建实例方法。正确?
答案 0 :(得分:1)
如果定义了方法talk
,则可以执行send(:talk)
,但由于未定义talk
,因此您无法执行此操作。此外,dog.send(:talk)
不会给您dog.talk = bruuuf
。如果talk=
已定义,dog.send(:talk=, ...)
将会执行此操作。
答案 1 :(得分:1)
首先关闭:您无法使用Object#send
设置实例变量。 Object#send
发送消息,它不设置实例变量。当然,您可以发送一条消息,该消息可能会或者可能不会再调用一个方法,该方法可能会或者可能不会依次设置实例变量,但这不是Object#send
的操作,而是执行任何方法被调用以响应您发送的消息。
如果要动态设置实例变量,请使用Object#instance_variable_set
:
class Dog
def initialize(**attrs)
attrs.each do |attr, value|
instance_variable_set(:"@#{attr}", value)
end
end
end
dog = Dog.new(talk: 'bruuuf')
但是,在这种情况下,看起来您实际上并不想设置实例变量,而是调用setter方法。 Setter方法的名称以=
符号结尾,例如Dog#talk=
:
class Dog
def initialize(**attrs)
attrs.each do |attr, value|
send(:"#{attr}=", value)
end
end
end
dog = Dog.new(talk: 'bruuuf')
当然,请注意,这假定方法Dog#talk=
实际存在。如果没有,您将获得NoMethodError
。