9

一般的な Ruby の質問: Ruby では、メソッドの一部ではなく、クラス内にあるコードをよく見かけます。例えば:

class DooDad
   attr_accessor :foo
end

また

class Teacher < ActiveRecord::Base
   has_many :students
end

attr_accessorメソッドとメソッドは、それぞれまたは引数でhas_many呼び出されると思いますが、そうですか? もしそうなら、これらの種類のステートメントはいつ実行されますか。私はこれを試しました::foo:students

class DooDad
  attr_accessor :foo
  puts "I happened!"
  @foo = 7
end

メソッドのこれらの部分を実行していないようですnew

dd = DooDad.new
dd.foo

nil を出力し、何も吐き出さputsない

それはどのように正確に機能しますか?

4

3 に答える 3

16

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()DooDadnew

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のインスタンスの変数について話していることになります。ddDooDaddefselfnewdd@foo = 7DooDad

この投稿はおそらく長すぎて、答えとして満足できないかもしれませんが、ある程度包括的であったことを願っています.

于 2012-08-21T21:38:06.973 に答える
7

has_manyおよびのようなメソッドattr_accessorは、実際にはモジュールまたはクラスのメソッドです。それらが通常のメソッドであり、他のメソッドと同じように引数で呼び出されることについては、あなたは絶対に正しいです。メソッドがクラス内 (メソッド定義の外) で直接呼び出される場合、そのメソッドはクラス自体で呼び出されます。

attr_accessorのドキュメントは次のとおりです。

于 2012-08-21T21:31:27.780 に答える
-2

それらは言語に組み込まれた構文糖衣であるため、テストと同じではありません。あなたが書くとき(例えば)

class Foo
  attr_accessor :bar
end

それは実際には略記です...

class Foo
  def bar
    @bar
  end

  def bar=(value)
    @bar = value
  end
end
于 2012-08-21T21:20:44.373 に答える