루비에서 include와 extend의 차이점은 무엇입니까?
루비 메타프로그래밍에 대해 생각해 보는 중입니다.믹스인/모듈은 항상 저를 혼란스럽게 합니다.
- include: 대상 클래스의 인스턴스 메서드로 지정된 모듈 메서드의 혼합
- extend: 대상 클래스의 클래스 메서드로 지정된 모듈 메서드에서 혼합
그래서 가장 큰 차이점은 이것뿐인가요 아니면 더 큰 용이 숨어 있나요? 예를 들어.
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!"
extend - 지정한 모듈의 메서드 및 상수를 대상의 메타 클래스(즉, 싱글톤 클래스)에 추가합니다.
- 에
Klazz.extend(Mod)
이제 클라즈는 모드의 방법을 가지고 있습니다(클래스 방법으로서). - 에
obj.extend(Mod)
는 (, mod의 .obj.class
에는 이러한 메서드가 추가되어 있습니다. extend
인 방법입니다.
include - 기본적으로 대상 모듈/클래스의 인스턴스 메서드로 지정된 모듈의 메서드에 혼합됩니다.
- 에
class Klazz; include Mod; end;
이제 클라즈의 모든 인스턴스는 모드의 방법(인스턴스 방법)에 액세스할 수 있습니다. include
는 컨테이너 클래스/컨테이너 내에서 호출되도록 의도되었기 때문에 비공개 메서드입니다.
그러나 모듈은 매우 자주 오버라이드합니다. include
원숭이를 이용한 행동.included
방법.이것은 레거시 레일즈 코드에서 매우 두드러집니다. 자세한 내용은 예후다 카츠가 제공합니다.
에 대한 정보include
동작입니다.
class Klazz
include Mod
end
- 모드가 이미 Klazz 또는 그 조상 중 하나에 포함되어 있는 경우, 포함 문은 영향을 주지 않습니다.
- 그것들이 충돌하지 않는 한, 그것은 또한 클라즈에 있는 모드의 상수를 포함합니다.
- 에게 Mod의 변수: Clazz는 모드변접수있수근습다니할에듈의모,있▁it다습)에 대한 액세스를 제공합니다.
@@foo
또는@@bar
- 순환 포함이 있는 경우 ArgumentError를 발생시킵니다.
- 모듈을 호출자의 직계 조상(예:에 하지만 모드는 클라즈의 사슬에 추가되지 않았습니다. 슈퍼 클래스 슈퍼 클래스초특급의그래서, 전화하기
super
Klazz#foo에서는 Mod#foo를 확인한 후 Klazz의 실제 슈퍼 클래스의 foo 메서드를 확인합니다.자세한 내용은 RubySpec을 참조하십시오.)
물론 루비 코어 문서는 항상 이러한 작업을 수행하기에 가장 적합합니다.RubySpec 프로젝트는 기능을 정확하게 문서화했기 때문에 환상적인 리소스이기도 했습니다.
#include
루비 스펙 루비 도크#included
루비 스펙 루비 도크#extend
루비 스펙 루비 도크#extended
루비 스펙 루비 도크#extend_object
루비 스펙 루비 도크#append_features
루비 스펙 루비 도크
당신이 한 말이 맞습니다.하지만, 그것보다 더 많은 것이 있습니다.
이 Klazz
모듈 및Mod
를 포함하여, 을 포함하여Mod
Klazz
에는 의예들설니다명의 있습니다.Klazz
에 합니다.Mod
의 방법.또는 확장할 수 있습니다.Klazz
와 함께Mod
수업하기 Klazz
에 합니다.Mod
의 방법.그러나 다음을 사용하여 임의 개체를 확장할 수도 있습니다.o.extend Mod
이 경우 개별 객체는 다음과 같이 됩니다.Mod
의 가 동일한 o
하지마.
맞습니다.
include는 실제로 (문서에서) append_features의 별칭입니다.
Ruby의 기본 구현은 이 모듈이 모듈 또는 그 상위 모듈 중 하나에 아직 추가되지 않은 경우 이 모듈의 상수, 메서드 및 모듈 변수를 모듈에 추가하는 것입니다.
모듈을 클래스로 구성하면 모듈 메서드를 인스턴스 메서드로 가져옵니다.
그러나 모듈을 클래스로 구성하면 모듈 메서드를 클래스 메서드로 가져옵니다.
들어 에는 모듈을 예로 들 수 .Module_test
다음과 같이 정의됩니다.
module Module_test
def func
puts "M - in module"
end
end
자, 모듈입니다.클래스를 정의하면A
다음과 같이:
class A
include Module_test
end
a = A.new
a.func
은 다음과 같습니다.M - in module
.
만약 우리가 라인을 교체한다면,include Module_test
와 함께extend Module_test
다시 합니다.undefined method 'func' for #<A:instance_num> (NoMethodError)
.
호출 변경하기a.func
A.func
이 다음과 같이됩니다.M - in module
.
위의 코드 실행으로부터, 우리가 모듈을 구성할 때, 그것의 메소드는 인스턴스 메소드가 되고, 우리가 모듈을 구성할 때, 그것의 메소드는 클래스 메소드가 되는 것이 분명합니다.
RubySpec을 탐색하는 팁을 포함하여 다른 모든 답변은 좋습니다.
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
사용 사례:
클래스에 모듈 재사용 가능 모듈을 포함하는 경우여기에는 메서드, 상수, 클래스, 하위 모듈 및 기타 선언이 참조됩니다.
클래스를 확장하는 경우모듈 재사용 가능 모듈로 확장하면 메서드와 상수가 복사됩니다.분명히, 주의하지 않으면 정의를 동적으로 복제하여 많은 메모리를 낭비할 수 있습니다.
ActiveSupport를 사용하는 경우:문제입니다. .included() 기능을 사용하면 포함 클래스를 직접 다시 작성할 수 있습니다. 문제 내부의 모듈 클래스 메서드가 포함 클래스로 확장(복사)됩니다.
작동하는 메커니즘에 대해서도 설명하고 싶습니다.제가 틀렸다면 수정해주세요.
사용할 때include
우리는 몇 가지 방법을 포함하는 모듈에 우리 반의 링크를 추가하고 있습니다.
class A
include MyMOd
end
a = A.new
a.some_method
객체에는 메서드가 없고 클래스와 모듈만 있습니다.그래서 언제a
메시지 수신some_method
검색 방법을 시작합니다.some_method
에a
의 고유 클래스, 그렇다면A
클래스 그리고 그 다음에A
클래스 모듈(역순으로, 마지막으로 포함된 승리)이 있는 경우.
사용할 때extend
우리는 객체의 고유 클래스에 있는 모듈에 링크를 추가하고 있습니다.따라서 A.new.extend(MyMod)를 사용하면 모듈에 링크를 A의 인스턴스 고유 클래스 또는a'
A하면 A) 에 링크를 입니다. 그리고 A.extend(MyMod)를 사용하면 A(객체의, 클래스도 객체임) 고유 클래스에 링크를 추가합니다.A'
.
method for 법방경:a
다음과 : a=> => 을 a' => vmdk에 연결했습니다. a => a' => a' => A' 모듈입니다.
또한 조회 경로를 변경하는 추가 방법이 있습니다.
a => a' => A에 추가된 모듈 => A => A에 포함된 모듈
제가 영어를 잘 못해서 죄송합니다.
저는 매우 유용한 기사를 발견했습니다.include
,extend
그리고.prepend
클래스 내에서 사용되는 메서드:
include
, 모듈 메소드는 클래스에 추가합니다.extend
모듈 메서드를 클래스 메서드로 추가합니다.에 따라 .
언급URL : https://stackoverflow.com/questions/156362/what-is-the-difference-between-include-and-extend-in-ruby
'source' 카테고리의 다른 글
명령줄을 통해 변수를 Ruby 스크립트로 전달 (0) | 2023.06.03 |
---|---|
VB 쓰는 법.순 람다 식 (0) | 2023.06.03 |
명령줄에서 안드로이드 에뮬레이터를 시작하려면 어떻게 해야 합니까? (0) | 2023.06.03 |
AWS S3: 액세스하려는 버킷은 지정된 끝점을 사용하여 주소를 지정해야 합니다. (0) | 2023.06.03 |
일정관리 응용프로그램에서 반복 이벤트를 모델링하는 가장 좋은 방법은 무엇입니까? (0) | 2023.06.03 |