2013-02-18 7 views
0

하는 방법을 다시 정의하는 다른 클래스의 방법 인쇄에 몇 가지 여분의 물건을 추가하여 인쇄 방법을 다시 정의합니다는 데 내가 간단한 방법 정의</p> <pre><code>class Printer def print p '1' end end </code></pre> <p>그리고 지금은 별도의 스크립트 소개와 간단한 클래스를

class Printer 

    alias :old_print :print 
    def print 
    old_print 
    p '2' 
    end 
end 

프로그래밍 방식으로이 작업을 수행 할 수 있습니까?

module Test 

    def self.redefine_print(arg) 
    # redefine Printer's print method so that it will print all of the stuff it should 
    # print, followed by the arg I specified 
    end 
end 

그래서 샘플 상호 작용처럼 보일 수 있습니다

>>>a = Printer.new 
>>>a.print 
1 
>>>Test.redefine_print("new stuff") 
>>>a.print 
1 
new stuff 
>>>Test.redefine_print("more") 
>>>a.print 
1 
new stuff 
more 

기존의 인스턴스가 프린터의 인스턴스가 생성되기 때문에, 그 인쇄를 (변경에 의해 영향을하고 즉시 배치되는 경우는 괜찮습니다)

+0

메서드를 재정의하려는 특별한 이유가 있습니까? 프린트 할 물건을 더 추가하는'Printer' 메소드를 가지고 계시지 않겠습니까? –

+0

당신은 프로그래밍 방식으로 * 수행하고 있습니다. 클래스 정의 밖에서 똑같은 일을 할 수있는 이유가 없습니다. 그건 ... 목적은 무엇입니까? 머리말/꼬리말/등을 추가하면됩니다. 당신은 그것을 위해 메타 프로그래밍을 할 필요가 없습니다. –

+0

내가 사용한 예제는 꽤 지나치게 단순화되었고, 그럴 수 있는지 여부를보기위한 것이었다. (다른 클래스의 다른 메소드를 재 정의하는 메소드). 내 솔루션은 아마 @RenatoZannon이 언급 한 라인을 따라 뭔가있을 것입니다. – MxyL

답변

0

define_method 또는 그 모듈을 사용할 수 있지만 잔인합니다 (그리고 매우 느릴 수도 있음).

class Printer 
    @@tokens = [] 

    def print 
    @@tokens.each do |token| 
     p token 
    end 
    end 

    def self.add_token(token) 
    @@tokens << token 
    end 
end 

Printer.add_token("foo") 

printer = Printer.new 
printer.print 
# foo 

Printer.add_token("bar") 
printer.print 
#foo 
#bar 

그것이 class_evaldefine_method를 사용하여 다른 클래스의 메소드를 재정의하는 것이 가능하지만 귀하의 질문에 대답하려면 : 클래스 변수와 클래스 대신 방법을 사용하는 것이 가능 (간단)입니다

class Printer 
    def print 
    p '1' 
    end 
end 

module Test 
    def self.redefine_print(arg) 
    old_print = Printer.instance_method(:print) 
    Printer.class_eval do 
     define_method(:print) do 
     old_print.bind(self).call 
     p arg 
     end 
    end 
    end 
end 

printer = Printer.new 
printer.print 
# 1 

Test.redefine_print("new stuff") 
printer.print 
# 1 
# new stuff 

Test.redefine_print("more") 
printer.print 
# 1 
# new stuff 
# more 
+0

'define_method'가 느린 이유는 무엇입니까? 메소드가 정의되면 소스 코드에 직접 정의 된 메소드와 다른 점이 다릅니다. 나는 동의하지만, 당신이 먼저 접근하면이 상황에 더 잘 어울린다. 그러나 일반적으로는 그렇지 않다. –

+0

정확하지 않습니다. 'define_method'는 메모리를 차지하는 closure를 포함합니다. 예에서 메소드의 이전 정의는 모두 참조해야합니다. 또한 메서드 캐시를 무효화합니다. –

+1

나는이 구체적인 예에 ​​당신과 동의한다. 그럼에도 불구하고'define_method'는 많은 경우에 훌륭하지만 신중하게 사용해야합니다. 코드에 대한 또 다른 메모 : 클래스 변수가 캡슐화를 쉽게 깨뜨리기 때문에 실제로 클래스 변수 대신 클래스 인스턴스 변수를 사용해야합니다. 예를 들어 http://martinfowler.com/bliki/ClassInstanceVariable.html을 참조하십시오. –

관련 문제

 관련 문제