2013-01-03 4 views
3

제목에서 알 수 있듯이 한 클래스에 정의 된 모든 인스턴스 메서드를 다른 클래스에 할당하고 싶습니다. 나는이 같은 ClassBClassA 복사 할 방법의 목록을 얻을 수에서 알 수 :한 클래스에서 다른 클래스로 인스턴스를 할당하는 방법

ClassA.instance_methods(false) 

그리고 나는이 같은 ClassB에 그들을 정의 할 수 있습니다 생각 :

ClassA.instance_methods(false).each do |method_name| 
    ClassB.method_define(method_name, [body here??]) 
end 

인가 해당 메서드 본문을 가져올 수있는 방법이 있습니까? 그렇다면이 메서드는 작동합니까? 그렇지 않은 경우에도이 작업을 수행 할 수있는 방법이 있습니까?

+5

왜이 작업을 수행 하시겠습니까? 어떤 목적으로 믹스 인/모듈을 사용하여이 작업을 수행 할 수 없습니까? –

+2

@ 존 : OP가 서브 클래 싱의 개념을 이해하지 못하는 놈이라고 생각하지 않습니다. 그의 질문을 문자 그대로 받아 보는게 어때? –

+0

코드가 귀하의 제목과 모순됩니다. ClassA와 ClassB (하나의 인스턴스가 아닌)가 동일한 메소드를 공유하기를 원합니다. John Naegle의 답변은 올바른 것입니다. ClassA의 모든 인스턴스 메소드를 모듈로 이동 한 다음이 모듈을 두 클래스에 포함하십시오. – BernardK

답변

3

당신이 할 수 있습니다 것은 혼합 인 인 것 같다 :

classBclassA을 상속해야하는 경우 http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html

module Debug 
    def whoAmI? 
    "#{self.type.name} (\##{self.id}): #{self.to_s}" 
    end 
end 
class Phonograph 
    include Debug 
    # ... 
end 
class EightTrack 
    include Debug 
    # ... 
end 
ph = Phonograph.new("West End Blues") 
et = EightTrack.new("Surrealistic Pillow") 
ph.whoAmI? » "Phonograph (#537766170): West End Blues" 
et.whoAmI? » "EightTrack (#537765860): Surrealistic Pillow" 
+0

나에게 적절한 대답이 보입니다. :) – BernardK

0

에서 촬영.

8

다른 사람은 이미 하위 클래스에 대해 말했습니다. 하지만 당신의 문자 질문에 대답하기 위해, 우리는 UnboundMethod 객체에 관여 것 :

class Object 
    def kokot; 'kokot' end 
end 

o = Object.new 
o.kokot 
#=> kokot 

3.kokot 
#=> kokot 

지금까지 너무 좋아. 이제 Numerickokot 방법을 재정의하자

class Numeric 
    def kokot; 'pica' end 
end 

o.kokot 
#=> kokot 
3.kokot 
#=> pica 

그러나 우리가 결정하는 경우에, 그 새로운 kokot 방법은 수치에 좋은 곳입니다, 그러나 다만 복소수 이전 kokot 방법을 사용하여 보관해야합니다. 우리는 이런 식으로 작업을 수행 할 수 있습니다 짧은에서

um = Object.instance_method :kokot 
#=> #<UnboundMethod: Object#kokot> 
Complex(2, 3).kokot # gives the redefined kokot method 
#=> pica 
Complex.module_exec { define_method :kokot, um } 
# Now we've just bound the old kokot to Complex 
Complex(2, 3).kokot 
#=> kokot 

는 관련 클래스들 사이에 "복사 및 붙여 넣기"방법 방법이있다. 타겟은 언 바운드 메소드 소스의 서브 클래스 일 필요가 있습니다. 내장 방법에 대한

um.source_location 
#=> ["(irb)", 2] 

, #source_location 반환 nil : 방법 #source_location 파일 및 #kokot가 정의 된 라인을 보여줍니다. 루비 2.0, RubyVM 클래스는 방법 #disassemble있다 : 어떤 경우에

RubyVM::InstructionSequence.disassemble(um) 
#=> (program listing goes here) 

를, 루비 바이트 코드는보기 위하여 그 아름다운 없습니다. #define_method 또는 UnboundMethod#bind조차 원래 요구 사항으로 돌아가서 호환되지 않는 개체에 메서드를 바인딩 할 수 있습니다. 이것은 #kind_of?을 재정의 같은 속임수에 의해 속임 할 수없는, 하나는 CLASS_OF 네이티브 코드() 함수 ...

가능한 보석에서

, Sourcify, RubyParserSorcerer이 관심있는 속임수해야합니다. (Thanks, @Casper.) 이것들을 사용하여 이론적으로 호환되지 않는 객체간에 #eval-추출 된 메소드 소스를 통해 코드를 이식 할 수 있습니다. 긴 방법으로,이 기술은 소스가 런타임에 사용 가능하지 않을 때마다 (예 : 자체 수정 소스) 실패하기 때문에 실현 가능한 메소드 전송에 여전히 미치지 못합니다.

0

루비 2.0에서는 모듈을 사용할 수 있습니다. Matz 명시 적으로 forbade this behavior from classes.

하지만 모듈의 instance_methods를 사용할 수 있습니다. 여기 send를 사용하는 이유는 그래서

ModuleA.instance_methods(false).each do |name| 
    meth = ModuleA.instance_method(name) 
    ClassB.send(:define_method, name, meth) 
end 

define_method은 개인 방법이다.

하지만 왜 이렇게할까요? 그냥 모듈을 포함하십시오.

개체에 동작을 적용하려면 모든 모듈에서 메서드를 바인딩 해제하고 모든 개체에 바인딩 할 수 있습니다. 이 당신이 원하는 경우

ModuleA.instance_method(:something).bind(some_object).call(args) 

만 블록의 수명에 대한 객체에 메소드를 추가 할뿐만 아니라, casting에서이 같은 gem that adds a convenience to doing delegation 좀 봐.

관련 문제