2011-03-22 16 views
2

저는 루비 스타터입니다. 나는 이것들 모두가 (출력에서) 꽤 유사하다는 것을 알았지 만, 나는 아래의 맥락에서 그 차이를 이해할 수 없었다. 예를 들어, 나는 수업을class_eval과 class << className의 차이점은 무엇입니까?

class Say 
    def self.hello 
    puts "hello" 
    end 
end 

이이

class << Say 
    def hi 
    puts "hi" 
    end 
end 

처럼 확장 할 수 있으며,이 같은

Say.class_eval do 
    def self.bye 
    puts "bye" 
    end 
end 

는 언제 <<class_eval를 사용해야합니까?

답변

13

class_eval은 실제로 class << className과 아무 관련이 없습니다.

A.class_eval do 
    ... 
end 

는 몇 가지 차이점과

class A 
    ... 
end 

에 해당합니다. class_eval은 블록 (또는 문자열이지만 잠시 동안 무시)을 사용합니다. 즉, 포함 된 어휘 범위에서 닫힙니다. 즉, 주변 범위의 로컬 변수를 사용할 수 있습니다. 공통 클래스 블록은 새로운 범위를 도입합니다. 마찬가지로 블록을 생성하여 여러 가지 다른 class_eval에 전달할 수 있으며 블록의 본문은 class_eval을 호출하는 클래스의 컨텍스트에서 실행됩니다.

class << className은 싱글 톤 클래스 className을 열어 클래스 메서드를 정의 할 수 있습니다.

class << A 
    def foo 
    ... 
    end 
end 

는 A가 클래스 (거의) 루비의 모든 객체는 싱글 수업을하고 사용 그들을 위해 방법을 정의 할 수 있습니다로 발생하는 경우가 OLY 클래스 메소드라는 것을

def A.foo 
    ... 
end 

주와 동일합니다 그 두 가지 구문 중 하나. class << obj의 장점은 주로 많은 싱글 톤 메소드를 한 번에 정의하는 경우입니다.

1

으로 이미 그들은 효과가 동일하지 않습니다 유사한 반면, 미묘한가 있습니다 (귀하의 예제에서 같은 일을하는 것 경우에도 class_eval가

class <<self 

과는 정말 많이하지를 가지며, 차이). 여기

번째 형태의 사용은 훨씬 더 다른 예를 명확 :

class A 

end 


a = A.new 
b = A.new 

class <<b 
    def say_hi 
    puts "Hi !" 
    end 
end 


b.say_hi # will print "Hi !" 
a.say_hi # will raise an undefined method 

A 및 B와 같은 클래스 A의 두 개체 그러나 우리는 소위 B의 메타 클래스하는 방법을 추가 메소드 say_hi는 b 객체에서만 사용할 수 있습니다.

관련 문제