2012-04-13 2 views
3

자바에 대한보다 역동적 인 대안을 찾고 있기 때문에 Ruby를 살펴보기 시작했습니다. 나는 당신이이 같은 예를 들어,의 정의 후 루비의 클래스를 수정하는 방법을 좋아한다 :Ruby mixins를 클래스 패치로 사용하는 방법

class A 
    def print 
    "A" 
    end 
end 

class B < A 
    def print 
    super + "B" 
    end 
end 

class A 
    alias_method :print_orig, :print 
    def print 
    print_orig + "+" 
    end 
end 

puts B.new.print # A+B 

이 지금은 유지 mixin과 동일한 작업을 수행하려고 :

class A 
    def print 
    "A" 
    end 
end 

class B < A 
    def print 
    super + "B" 
    end 
end 

module Plus 
    alias_method :print_orig, :print 
    def print 
    print_orig + "+" 
    end 
end 

A.extend(Plus) # variant 1 
B.extend(Plus) # variant 2 
class A # variant 3 
    include Plus 
end 
class B # variant 4 
    include Plus 
end 
puts B.new.print 

그러나 변종 중 어느 것도 생산하지 예상 된 결과. BTW, 예상되는 결과는 다음과 같습니다. 믹스를 사용하여 클래스 A를 '패치'하여 해당 동작을 수정할 수 있기를 원합니다. 믹스 인을 쓰고 싶습니다. 같은 행동으로 여러 클래스를 '패치'하고 싶습니다.

내가 원하는 것을 할 수 있습니까? 그렇다면 어떻게?

답변

5

잘못된 컨텍스트에서 실행되기 때문에 모듈 코드가 작동하지 않습니다. 문맥을 A으로 실행해야하지만 대신 Plus의 컨텍스트로 평가됩니다. 즉, selfPlus에서 A으로 변경해야합니다.

관찰 :

class A 
    def print 
    "A" 
    end 
end 

class B < A 
    def print 
    super + "B" 
    end 
end 

module Plus 
    self # => Plus 
    def self.included base 
    self # => Plus 
    base # => A 
    base.class_eval do 
     self # => A 
     alias_method :print_orig, :print 
     def print 
     print_orig + "+" 
     end 
    end 
    end 
end 

A.send :include, Plus 
B.new.print # => "A+B" 
+0

좋은 예, +1. – Ernest

1

당신은 정말 이런 식으로 유지 mixin을 사용할 수 없습니다. 클래스와 믹스 인간에 충돌이 발생합니다. Mixins implicitly resolve the conflict by linearization. 결론 : 충돌이있는 경우, 클래스의 메서드가 mixin보다 선호됩니다. 이 문제를 해결하려면 Sergio' Tulentsev's approach and have the mixin change its base class aggressively을 사용할 수 있습니다.

또는 메소드를 반사적으로 추가 할 수 있습니다. 이 예를 고려해보십시오.이 예는 Mark's blog에서 도난당했습니다.

class Talker 

    [:hello, :good_bye].each do |arg| 
    method_name = ("say_" + arg.to_s).to_sym 
    send :define_method, method_name do 
     puts arg 
    end 
    end 

end 


t = Talker.new 
t.say_hello 
t.say_good_bye 
관련 문제