2014-03-14 3 views
1

제목에 사과하여보다 명확하게 이해할 수 있도록 제안합니다.Ruby - 다른 모듈을 포함하는 모듈의 클래스 및 인스턴스 메소드를 얻으시겠습니까?

나는 이 클래스 안에있을 때 새로운 클래스 메소드와 인스턴스 메소드를 얻게 될 모듈 (우리는 M으로 표시 할 것임)을 만들었습니다. (용어가 정확하지 않으면 죄송합니다). 이것은 아래 코드에서 A::ModuleInstanceMethods 모듈을 포함하는 클래스 F에 의해 달성됩니다.

이제이 작업을 완료했습니다. 모듈 M을 포함하는 새 모듈 (이 새 모듈은 M'이라고합니다)을 만들려고합니다. 따라서 M'이 클래스에 포함되면 클래스가 생성되어야합니다. 적절한 클래스와 인스턴스 메소드 F. 이것은 내가 붙어있는 곳이다. 이러한 클래스의 예는 아래 코드에 G입니다.

include 모듈 M'' (모듈 M''에는 M'이 포함됩니다)이 동일한 기능을 갖기를 바랍니다. 예는 아래 코드에 H 클래스입니다. M''' (자체는 M''을 포함), M'''' (자체는 M'''을 포함) 등의 클래스에도 동일하게 적용해야합니다. 상속 계층 구조와 매우 비슷합니다.

텍스트 설명이 혼란 스럽다면 아래 코드를 읽으십시오. 특히, G.class_method_oneH.class_method_one을 호출하여 발생하는 오류를 해결하고 싶습니다. 그러나이를 수행하는 데 필요한 지식이 부족합니다.

내가 관심있는 수업에서 extendA::ModuleClassMethods 모듈을 사용할 수는 있지만이 작업을 피하고 싶습니다. 동일한 것은 수동으로 self.included 함수의 부분을 base.instance_of? Class과 함께 A::ModuleInstanceMethods에 추가하여 얻을 수도 있지만 가능한 경우 많은 다른 사이트에서 동일한 코드를 복사하여 붙여 넣는 대신 프로그래밍 방식으로 수행하고 싶습니다.

module A 
    module ModuleClassMethods 
    def class_method_one 
     2 
    end 
    end 

    module ModuleInstanceMethods 
    def instance_method_one 
     3 
    end 

    def self.included(base) 
     if base.instance_of? Class 
     base.extend(A::ModuleClassMethods) 
     elsif base.instance_of? Module 
     # Intended functionality: 
     # When modules that `include` A::ModuleInstanceMethods are themselves 
     # included in a class (such as module `A::D` included in class `F`), 
     # class `F` will get the functions defined in the A::ModuleClassMethods 
     # module as class level methods 
     end 
    end 
    end 

    module D 
    include A::ModuleInstanceMethods 
    end 

    module E 
    include D 
    end 
end 

class F 
    include A::ModuleInstanceMethods 
end 

class G 
    include A::D 
end 

class H 
    include A::E 
end 

F.class_method_one # 2 
F.new.instance_method_one # 3 

G.new.instance_method_one # 3 
# below statement fails 
# G.class_method_one 

H.new.instance_method_one # 3 
# below statement fails 
# H.class_method_one 

감사합니다.

+1

'연장 사용하지 않겠습니다.' 왜? 문제를 해결하는 가장 쉽고 청결한 방법이라고 생각합니다. –

+0

'extend'는 문제를 해결하는 가장 쉬운 방법입니다. 나는 내 대답에 대한 당신의 의견을 볼 때까지 그것이 가장 깨끗한 방법이 아닐 것이라고 말하려고했다. 나는 당신이 이것에 맞다고 생각합니다. – yanhan

답변

0

나는 그것을 알아 낸 것 같습니다. 이 솔루션은 module_eval을 사용합니다. module의 경우 을 호출하는 self.included 함수가 추가됩니다. 나는 더 우아한 해결책에 대해 배우는 것을 꺼려하지 않을 것이다.

module A 
    module ModuleClassMethods 
    def class_method_one 
     2 
    end 
    end 

    module ModuleInstanceMethods 
    def instance_method_one 
     3 
    end 

    def self.included(base) 
     if base.instance_of? Class 
     base.extend(A::ModuleClassMethods) 
     elsif base.instance_of? Module 
     base.module_eval { 
      def self.included(base) 
      A::ModuleInstanceMethods.included(base) 
      end 
     } 
     end 
    end 
    end 
end 
+1

이것은 아마도 문제를 일으킬 수 있습니다. 모듈 사용자는 자신의'included' 훅을 정의하고자 할 수 있습니다. 너의 것 중 하나가 사용자의 것을 오버라이드하거나 사용자의 의지가 너의 것보다 우선한다. 하나는 그것을 해킹 할 수 있지만 더 좋은 방법이 있는지 궁금해. 또한 [[Object # define_singleton_method'] (http://ruby-doc.org/core-2.1.1/Object.html#method-i-define_singleton_method)을 살펴보십시오. –

+0

당신은 아주 좋은 지적을 가지고 있습니다. 나는 그것을 생각하지 않았다. +1 – yanhan

관련 문제