attr_accessor
やのようなメソッドはhas_many
、Ruby キーワードのように見える (模倣する) ため、「模倣メソッド」と呼ばれることがよくありますが、実際には、あなたや他の人が正しく指摘しているように、メソッド呼び出しです。
dd = DooDad.new
dd.foo
nil を出力し、何も吐き出さputs
ない
それはどのように正確に機能しますか?
クラス定義の内部にいる場合、すべてのメソッド呼び出しと「変数定義」の暗黙的な受信者はself
であり、あなたの場合はDooDad
.
だから書いてる時は
class DooDad
@foo = 1
end
そのクラス定義の内部にいるため、実際には でインスタンス変数を定義しています。self
これはたまたまクラス自体です。(および他のクラス、モジュール、またはメソッド定義の外側)
一方、メソッドは、メタプログラミングの助けを借りて、 class からインスタンス化されたオブジェクトのインスタンス変数のattr_accessor
アクセサ メソッドを生成します。DooDad
あなたの例に戻ります:
class DooDad
attr_accessor :foo
puts "I happened!"
@foo = 7
end
上記の内容で、2 つの異なる @foo 変数を扱っていることを理解する必要があります。1 つはクラス DooDad のインスタンス (つまり) で、もう 1 つはクラス DooDad 自体DooDad.new
( を記述して作成したもの) です。@foo = 7
new
クラスでメソッドを呼び出すときは、そのインスタンスを作成します。
dd = DooDad.new
#=> dd is now an object of class DooDad
dd.foo
#=> You just called the "getter" method for an instance variable foo of object dd, which was never defined before, that's why it's returning nil.
このputs "I happened!"
ステートメントは、他の 2 つのステートメントと同様に、クラスがロードされるとすぐに評価されますが、呼び出したときは評価されませんnew
。あなたが説明した動作( を呼び出すときに何かをする)が必要な場合は、 を呼び出すときに呼び出される のメソッドを new
実装することをお勧めします。initialize()
DooDad
new
class DooDad
attr_accessor :foo
def initialize()
puts "I happened!"
@foo = 7
end
end
dd = DooDad.new
#=> outputs "I happened!" and sets dd.foo = 7
dd.foo
#=> 7
しかし、なぜand not@foo = 7
のインスタンス変数を設定するのでしょうか? キーワードでメソッドを定義すると、新しいスコープに入ります (スコープ ゲートを通過します)。はもはやクラスではなく、 で作成したそのクラスのインスタンスです。したがって、メソッド定義の内部に記述しているときは、クラス自体ではなく、 classのインスタンスの変数について話していることになります。dd
DooDad
def
self
new
dd
@foo = 7
DooDad
この投稿はおそらく長すぎて、答えとして満足できないかもしれませんが、ある程度包括的であったことを願っています.