1

我有以下代码:

class Dog
  def initialize(attributes = {})
    attributes.each do |attr, value|
      send("#{attr}", value)
    end
  end
end


dog = Dog.new({:talk => 'bruuuf'})

我在初始化中得到一个块:未定义的方法“谈话”用于#(NoMethodError)

发送不应该做类似的事情:

dog.talk = bruuuf为什么不让我这样做?此外,这不会设置实例变量,但会创建实例方法。正确的?

4

2 回答 2

1

如果talk定义了方法,你可以做send(:talk),但由于talk没有定义,你不能这样做。此外,dog.send(:talk)不会给你dog.talk = bruuuf。只要talk=有定义,dog.send(:talk=, ...)就会去做。

于 2013-11-14T06:16:10.793 回答
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.

于 2013-11-14T10:53:14.113 回答