2013-07-09 4 views
14

Ruby의 믹스 인 메소드에 대한 기사 (extendinclude)를 읽었으며 여전히 동작에 대해 확신하지 못했습니다. 제가 extend가 연장하고있는 모듈 단일 메소드로 지정된 모듈 인스턴스 메소드를 추가 할 것이라는 및 include 본질적 효과적으로 정의를 포함하고있는 하나의 모듈의 내용 (방법 상수, 변수)을 추가 할 것을 이해 그것들을 수신기에.Ruby 믹스 : 확장 및 포함

그러나 일부 땜질 후, 행동이 명시하는 방법에 대한 느낌을 얻을려고, 나는 몇 가지 질문 있어요. 여기 내 테스트 설정입니다 : 그래서

module Baz 
    def blorg 
    puts 'blorg' 
    end 
end 

module Bar 
    include Baz 
    def blah 
    puts 'blah' 
    end 
end 

module Foo 
    extend Bar 
end 

class Bacon 
    extend Bar 
end 

class Egg 
    include Bar 
end 

나는, 모듈 Bar 이익 인스턴스로 인해 포함 방법과 그들이 자체에 정의 된 것처럼 Baz (#blorg)에 정의 된 메소드 및 클래스 Bacon 이익을 예상하는대로 싱글 방법 나아가서 Bacon::blahBacon::blorg.

Bacon.blah # => blah 
Bacon.blorg # => blorg 

그리고 클래스 Egg 이익 인스턴스 메소드로 Bar (지금 #blah#blorg)에 정의 된 방법.

Egg.new.blah # => blah 
Egg.new.blorg # => blorg 

나는 모두 그렇게 얻을 수있다.

그러나, 나는 내가 #ancestors#is_a? 방법을 사용에게서 얻는 반응을 이해하지 않습니다.

Bacon.ancestors # => [Bacon, Object, Kernel, BasicObject] 
Bacon.is_a? Bar # => true 

Egg.ancestors # => [Egg, Bar, Baz, Object, Kernel, BasicObject] 
Egg.is_a? Bar # => false 

그 모듈에 대해 조회 할 때 모듈을 연장 true를 반환하는 #is_a? 방법을 일으키는 것 같다,하지만이 클래스의 조상에 추가되지 않으며, 포함에 관해서 반대 :의 조상 클래스는 모듈이 포함되어 포함되어 있지만 쿼리 할 때 #is_a? 방법은 false를 반환합니다. 왜 이런 일이 생길까요?

+0

+1이 질문의 위대한 형식입니다. – sargas

답변

24

차이점은 include이 포함 된 클래스를 포함 클래스의 조상에 추가하는 반면 extend은 확장 클래스를 확장 클래스의 단일 클래스의 조상에 추가한다는 점입니다. 휴.

Bacon.ancestors 
#=> [Bacon, Object, Kernel, BasicObject] 

Bacon.singleton_class.ancestors 
#=> [Bar, Baz, Class, Module, Object, Kernel, BasicObject] 

Bacon.new.singleton_class.ancestors 
#=> [Bacon, Object, Kernel, BasicObject] 

Bacon.is_a? Bar 
#=> true 

Bacon.new.is_a? Bar 
#=> false 

을 그리고 Egg 클래스

Egg.ancestors 
#=> [Egg, Bar, Baz, Object, Kernel, BasicObject] 

Egg.singleton_class.ancestors 
#=> [Class, Module, Object, Kernel, BasicObject] 

Egg.new.singleton_class.ancestors 
#=> [Egg, Bar, Baz, Object, Kernel, BasicObject] 

Egg.is_a? Bar 
#=> false 

Egg.new.is_a? Bar 
#=> true 

은 그래서 foo.is_a? Klass 실제로하는 일은 foo.singleton_class.ancestorsKlass 포함되어 있는지 여부를 확인하는 것입니다 :의 처음 발생하는 관찰하자. 다른 일은 인스턴스가 생성 될 때 클래스의 모든 조상이 인스턴스의 싱글 톤 클래스의 조상이된다는 것입니다.

Egg.ancestors == Egg.new.singleton_class.ancestors 

그래서이 모든 것이 무엇을 의미 하는가 : 그래서 이것은 어떤 클래스의 모든 새로 생성 된 인스턴스에 대해 true로 평가합니다? class << self 그냥 이상한 구문입니다

module A 
    def foobar 
    puts 'foobar' 
    end 
end 

class B 
    extend A 
end 

class C 
    class << self 
    include A 
    end 
end 

B.singleton_class.ancestors == C.singleton_class.ancestors 
#=> true 

는 싱글 톤 클래스에 도착 : extendinclude이 다른 수준에서 같은 일을, 나는 다음과 같은 예는 클래스를 확장하는 두 가지로이 명확 본질적으로 동등하게 희망 . 그래서 extend은 싱글 톤 클래스에서 include의 줄임말입니다.

0
Egg.is_a? Egg # => false 

Egg 클래스의 인스턴스를 포함 (효과적으로)하면 변경됩니다. 꽤 동일하지 않지만,이

class Egg < Bar 
end 

같은 일을 매우 유사하다 할 때 클래스 메소드를 추가합니다 확장, 그래서 이것은

class Bacon 
    class << self 
    include Bar 
    end 
end 

당신이 할 수있는 같은 일을 매우 유사하다 클래스의 변경 인스턴스를 포함하는 것으로 생각하십시오. 여기에서 extend는 실제로 클래스를 변경합니다.

+0

아마도 잘못 입력 한 것이지만 'Egg.new.is_a? Egg'는'true'를 반환합니다. '에그 .is_a? Egg # => false'? – DesAdams

+0

예. 나는 그것을 편집 할 것이다. – Olives