2012-02-27 2 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 variable이 아닌 instance 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