2

Ruby の興味深い動作を明らかにする奇妙なバグをコードで見つけました。うまくいけば、誰かがこのように動作する理由を説明できます。

インスタンス変数 @foo を持つクラスと、ローカル スコープの変数 foo を参照するメソッドがありました。メソッドの一部を誤って foo への参照を残してリファクタリングしました。スコープで定義されなくなった変数。代わりに @foo を指すことになりました。foo を変更すると @foo が変更され、その逆も同様です。

簡易版: EDIT : ImOutOfNames を追加。

class ImOutOfNames
    attr_accessor :foo # the culprit!
end

class Bar < ImOutOfNames
    def initialize
        @foo = "that is a tasty burger"
    end

    def bar_method_1
        foo = "Come on Yolanda, whats Fonzie like?"
        bar_method_2
    end

    def bar_method_2
        puts foo
    end
end

そして bar_method_1 と bar_method_2 の出力は「それはおいしいハンバーガーです」でした。エラーが発生することを期待していました。たとえば、上記のコードを実行すると取得されます

NameError: undefined local variable or method

私はより上級の開発者にも見てもらいましたが、彼はやや困惑し、動作を確認しました.

これは予期された動作ですか? @variables の仕組みを誤解していますか、それとも何か問題がありますか?

4

2 に答える 2

4

以前のバグのあるコードは、インスタンス変数にアクセスする メソッドfooを作成したattr_accessor定義にある可能性があります。

コードが次のような場合、同じ動作をすることができます。

class Bar

  attr_accessor :foo

  def initialize
    @foo = "that is a tasty burger"
  end

  def bar_method_1
    foo = "Come on Yolanda, whats Fonzie like?"
    bar_method_2
  end

  def bar_method_2
    puts foo
  end
end

attr_accessor 呼び出しは、オブジェクトに 2 つのメソッドを定義します。

def foo
  @foo
end

def foo=(value)
  @foo = value
end

したがって、ローカル変数が定義されていない場合、メソッドが使用されましたが、この例では attr_accessor を呼び出さなかったため、メソッドが定義されておらず、bar_method_2 で使用するローカル変数がなかったため、呼び出しが失敗しました。

于 2011-08-18T04:33:32.953 に答える
0

@foo インスタンス変数の attr アクセサーはありますか? これは、これが起こる可能性のある 1 つの方法です。

一般に、ローカルスコープの変数に同じ名前を使用しないことをお勧めしますが、それが何らかのメソッドからのものであるかどうかを調べることができます

self.method(:foo)

またはそれが定義されている場合でも

defined? foo

ruby ランタイムを有利に使用することで、一部のコードの神秘主義と魔法の性質が確実に軽減されます。

于 2011-08-18T04:33:15.993 に答える