1

次のコードがあります。

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


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

そして、initialize': undefined method `talk' for # (NoMethodError) でブロックを取得します。

send は次のようなことをしているはずではありません:

dog.talk = bruuufなぜそうさせてくれないのですか?また、これはインスタンス変数を設定しませんが、インスタンス メソッドを作成します。右?

4

2 に答える 2

1

メソッドtalkが定義されていればできますがsend(:talk)、 がtalk定義されていないため、それはできません。さらに、dog.send(:talk)あなたに与えませんdog.talk = bruuuftalk=定義されていれば、それdog.send(:talk=, ...)を行います。

于 2013-11-14T06:16:10.793 に答える
1

まず、インスタンス変数を で設定することはできませんObject#sendObject#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 メソッドを呼び出したいようです。セッター メソッドには、=記号で終わる名前があります。たとえば、次のようになり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 に答える