2012-02-27 12 views
16

class_evalを使用して、現在のクラスのコンテキストで実行されるコードを記述しています。次のコードでは、属性値の変更のためのカウンタを追加したいと思います。私の場合には、class Foo下 -`class_eval`文字列内の可変スコープとは何ですか?

class Class 
    def attr_count(attr_name) 
    attr_name = attr_name.to_s 
    attr_reader attr_name # create the attribute's getter 
    class_eval %Q{ 
     @count = 0 
     def #{attr_name}= (attr_name) 
     @attr_name = attr_name 
     @count += 1 
     end 

     def #{attr_name} 
     @attr_name 
     end 
    } 
    end 
    end 
class Foo 
    attr_count :bar 
end 

f = Foo.new 
f.bar = 1 

class_evalの私の理解では、ランタイムクラスのコンテキストでブロックを評価していることです。

class Foo 
    attr_count :bar 
    @count = 0 
    def bar= (attr_name) 
    @attr_name = attr_name 
    @count += 1 
    end 

    def bar 
    @attr_name 
    end 
end 

上記のコードはエラーが@count += 1によって引き起こされる、というエラーになったしかし:私はとして実行同様の上記のコードを期待しています。私はなぜ@countnil:NilClassをそのスーパーとして持っているのか分かりませんか?一方

(eval):5:in `bar=': undefined method `+' for nil:NilClass (NoMethodError) 

、@selmanはインスタンスメソッド内@count割り当てを置くためのソリューションを与えているし、それが動作します。

class Class 
    def attr_count(attr_name) 
    #... 
    class_eval %Q{ 
     def #{attr_name}= (attr_name) 
     @attr_name = attr_name 
     if @count 
      @count += 1 
     else 
      @count = 1 
     end 
     end 
     #... 
    } 
    end 
end 

なぜ可変スコープが機能するのですか? class_evalは次の文字列をどのように実行しますか?

+0

CS169クラスはどのように気に入っていますか? :) –

答えて

12

class_evalではありません。約@countです。この変数をクラス・レベルで定義すると、class instance variableinstance variableではありません。

class Class 
    def attr_count(attr_name) 
    attr_name = attr_name.to_s 
    attr_reader attr_name # create the attribute's getter 
    class_eval %Q{ 
     def #{attr_name}= (attr_name) 
     @attr_name = attr_name 
     if @count 
      @count += 1 
     else 
      @count = 1 
     end 
     end 

     def #{attr_name} 
     @attr_name 
     end 
    } 
    end 
end 

class Foo 
    attr_count :bar 
end 

f = Foo.new 
f.bar = 1 
+0

それは動作します。私は 'class_eval'メソッドの' @ count'と '@@ count 'の違いでまだ混乱しています。私の理解は1です。 'class_eval'に渡された文字列は' class Foo'が呼び出されたときに評価されます。 2. '@ count'は' Foo'のすべてのインスタンスのインスタンス変数でなければなりません。どうしてクラス変数 '@@ count 'を使って**インスタンス変数**のように振る舞うのですか?私はトピックが複雑であることを知っています、あなたは私が読むことができるいくつかの参照を持っていますか? – steveyang

+0

この[ブログの投稿](http://martinfowler.com/bliki/ClassInstanceVariable.html) –

+0

こんにちは、@selmen。 @@ countは実際にインスタンス変数として振る舞いません。クラス変数として動作します。それは私が期待したものではありません – steveyang

関連する問題