3

私はコードをもっている:

class A
  attr_accessor :somevar

  def a
    somevar = 'something'
    puts @somevar
  end

  def b
    send :somevar=, 'something'
    puts @somevar
  end

end

A.new.a #=> nil
A.new.b #=> 'something'

なぜ違いがあるのですか?ライターを介してインスタンス変数を割り当てることができないのはなぜですか? しかし、メソッド (セッター) が呼び出される代わりにローカル変数が作成されたのはなぜですか?

4

2 に答える 2

7

attr_accessor :somevarインスタンス変数を参照します@somevar@インスタンス変数の前には記号を付ける必要があります。メソッド内の記号のない 'somevar' などの他のすべての変数@は、オブジェクトのインスタンス変数ではなく、そのメソッドまたはスコープの単なるローカル変数です。

したがって、メソッド「a」の最初の行を次のように変更します

@somevar = 'something'

あなたが期待する答えが得られます。

関連メモ: Ruby ではインスタンス変数を宣言する必要はなく、@somevar型表記で作成するだけです。このattr_accessorメソッドは、そのインスタンス変数のセッターとゲッターを作成します。

Ruby のメソッドはオブジェクトに関連付けられているため、クラス A が独自の somevar セッター メソッドを呼び出すには、 を記述する必要がありますself.somevar = 'something'。そうしないと、Ruby パーサーは、ローカル変数を作成しているだけだと認識します。

次のようにするだけでaからメソッドを呼び出すことができるため、これは混乱を招く可能性があります。b

def b
  send :somevar=,'something'
  puts @somevar
  a  # would invoke its own method 'a'
end

しかし、setter メソッドsomevar=は、同じ表記法でローカル変数を作成するとあいまいです。

somevar='something'  # Ruby assumes you want to create a local variable

したがって、 somevar セッター メソッドを呼び出すには、次のように自分自身でメソッドを呼び出していることを明示的に示す必要があります。

self.somevar = 'something'

あなたが呼び出したとき、send :somevar=,'something'あなたは somevar インスタンスメソッドも呼び出していました。

于 2012-06-06T11:51:01.650 に答える
1

メソッド a が somevar というローカル変数を作成しているためです。これは、Ruby のちょっとした癖の 1 つにすぎません。self.somevar = 'something'またはを実行することで、これを回避できます@somevar = 'something'

于 2012-06-06T11:47:20.793 に答える