문제

Ruby Metaprogramming 주위에 머리를 잡았습니다. 믹스 인/모듈은 항상 나를 혼란스럽게합니다.

  • 포함: 지정된 모듈 메소드에서 혼합 인스턴스 방법 대상 클래스에서
  • 연장하다: 지정된 모듈 메소드에서 혼합 수업 방법 대상 클래스에서

그렇다면 큰 차이점은 이것이나 더 큰 용이 숨어 있습니까?예를 들어

module ReusableModule
  def module_method
    puts "Module Method: Hi there!"
  end
end

class ClassThatIncludes
  include ReusableModule
end
class ClassThatExtends
  extend ReusableModule
end

puts "Include"
ClassThatIncludes.new.module_method       # "Module Method: Hi there!"
puts "Extend"
ClassThatExtends.module_method            # "Module Method: Hi there!"
도움이 되었습니까?

해결책

당신이 말한 것은 맞습니다. 그러나 그것보다 더 많은 것이 있습니다.

수업이있는 경우 Klazz 그리고 모듈 Mod, 포함 Mod 안에 Klazz 인스턴스를 제공합니다 Klazz 액세스 Mod의 방법. 또는 연장 할 수 있습니다 Klazz ~와 함께 Mod 주는 수업 Klazz 액세스 Mod의 방법. 또한 임의의 객체를 확장 할 수 있습니다 o.extend Mod. 이 경우 개별 객체가 발생합니다 Mod동일한 클래스를 가진 다른 모든 객체에도 o 하지 마라.

다른 팁

연장하다 - 지정된 모듈의 메소드와 상수를 대상의 메타 클래스 (예 : 싱글 톤 클래스)에 추가합니다.

  • 전화하면 Klazz.extend(Mod), 이제 Klazz는 MOD의 방법을 가지고 있습니다 (수업 방법으로)
  • 전화하면 obj.extend(Mod), 이제 OBJ는 MOD의 메소드 (인스턴스 방법)를 가지고 있지만 다른 인스턴스는 없습니다. obj.class 이러한 방법이 추가되었습니다.
  • extend 공개 방법입니다

포함 - 기본적으로 지정된 모듈의 메소드를 대상 모듈/클래스의 인스턴스 메소드로 혼합합니다. 예를 들어

  • 전화하면 class Klazz; include Mod; end;, 이제 Klazz의 모든 인스턴스는 MOD의 방법에 액세스 할 수 있습니다 (인스턴스 방법으로)
  • include 컨테이너 클래스/모듈 내에서 호출되기 때문에 개인 방법입니다.

하지만, 모듈은 매우 자주 우세하다 include원숭이 패치에 의한 행동 included 방법. 이것은 레거시 레일 코드에서 매우 두드러집니다. Yehuda Katz의 자세한 내용.

에 대한 자세한 내용 include, 다음 코드를 실행한다고 가정하면 기본 동작으로

class Klazz
  include Mod
end
  • MOD가 이미 Klazz 또는 조상 중 하나에 포함 된 경우 포함 진술은 영향을 미치지 않습니다.
  • 또한 클래쉬하지 않는 한 Klazz의 Mod의 상수가 포함됩니다.
  • Klazz의 모듈 변수에 대한 액세스 권한을 부여합니다. @@foo 또는 @@bar
  • Cyclic Include가있는 경우 ArgumenterRor를 올리십시오
  • 발신자의 즉각적인 조상으로 모듈을 첨부합니다 (즉, Klazz.ancestors에 모드를 추가하지만 Mod는 Klazz.superclass.superclass.superclass의 체인에 추가되지 않습니다. super Klazz#foo에서 Klazz의 Real Superclass 's Foo 메소드를 확인하기 전에 Mod#foo를 확인합니다. 자세한 내용은 RubySpec을 참조하십시오.).

물론, 루비 코어 문서 항상 이런 일을하기에 가장 좋은 곳입니다. RubySpec 프로젝트 또한 기능을 정확하게 문서화했기 때문에 환상적인 리소스였습니다.

맞습니다.

무대 뒤에서 포함하는 것은 실제로 별명입니다. 부록, (문서에서) :

Ruby의 기본 구현은이 모듈이 이미 Amodule 또는 조상 중 하나에 추가되지 않은 경우이 모듈의 상수, 메소드 및 모듈 변수를 AMODULE에 추가하는 것입니다.

RubySpecs를 파헤칠 팁을 포함하여 다른 모든 답변은 좋습니다.

https://github.com/rubyspec/rubyspec/blob/master/core/module/include_spec.rb

https://github.com/rubyspec/rubyspec/blob/master/core/module/extend_object_spec.rb

사용 사례에 관해서는 :

만약 너라면 포함 클래스 클래스에서 모듈리스 블리 모드를 포함하여 방법, 상수, 클래스, 하위 모듈 및 기타 선언이 참조됩니다.

만약 너라면 연장하다 클래스 클래스 thatextends with module reusablemodule, 그러면 메소드와 상수가 가져옵니다. 복사. 분명히 조심하지 않으면 정의를 동적으로 복제하여 많은 메모리를 낭비 할 수 있습니다.

ActivesUpport :: Concent를 사용하는 경우 .included () 기능을 사용하면 클래스를 포함하여 직접 다시 작성할 수 있습니다. 관심사 내부의 모듈 클래스 메드가 얻습니다 펼친 (복사) 포함 클래스로.

또한 메커니즘이 작동하는 것처럼 설명하고 싶습니다. 내가 옳지 않다면 수정 해주세요.

우리가 사용할 때 include 우리는 클래스에서 몇 가지 방법이 포함 된 모듈로 연결을 추가하고 있습니다.

class A
include MyMOd
end

a = A.new
a.some_method

객체에는 방법이 없으며 클라스와 모듈 만 그렇습니다. 그렇게 할 때 a Mesage를받습니다 some_method 검색 방법을 시작합니다 some_method 안에 aEigen Class, 그런 다음 A 수업과 그 다음에 연결되었습니다 A 클래스 모듈이있는 경우 (역 순서로, 마지막으로 포함).

우리가 사용할 때 extend 우리는 Object의 Eigen 클래스의 모듈에 연결을 추가하고 있습니다. 따라서 A.New.extend (MyMod)를 사용하면 A의 인스턴스 Eigen 클래스에 모듈에 연결을 추가하거나 또는 a' 수업. 그리고 우리가 a.extend (mymod)를 사용한다면 (대상, 클래스도 개체입니다) 고유 A'.

따라서 방법 조회 경로 a 다음과 같습니다.

또한 조회 경로를 변경하는 프리 엔드 방법이 있습니다.

a => a '=> prepeded modulesto a => a => 포함 모듈에

내 하찮은 영어 실력에 죄송하다는 말씀을 드리고 싶습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top