2012-04-03 8 views
2

Ich suche nach einer Methodenverkettung. Ich habe den folgenden Code:Erkennen, wenn eine Methode verkettet ist

class MyClass 

    attr_accessor :handler 

    def do_a 
    puts 'i just did a' 
    self.handler = 'a' 
    self 
    end 

    def do_b_if_a 
    puts 'i just did b' if handler == 'a' 
    end 

end 

So sind die folgenden Werke:

irb > test = MyClass.new 
=> #<MyClass:0x007fa44ced9a70 @handler=nil> 
irb > test.do_a 
'i just did a' 
irb > test.do_a.do_b_if_a 
'i just did a' 
'i just did b' 

Was ich will DONT ist arbeiten, wenn ich do_a ersten Mal nennen sie die Handler-Sets, die nun bedeutet do_b_if_a kann sein jederzeit angerufen. Aber ich möchte nur, dass es angerufen wird, wenn es mit do_a angekettet ist, wie mache ich das?

Antwort

0

Ich glaube, Sie Tracking-Zustand in der falsche Ort. Sie würden mit ähnlich etwas besser dran zu Active Abfrage-Schnittstelle, zum Beispiel:

class MyClass 
    attr_accessor :handler 

    def do_a 
    puts 'i just did a' 
    with_handler 'a' 
    end 

    def do_b_if_a 
    puts 'i just did b' if handler == 'a' 
    end 

private 

    def with_handler(h) 
    o = dup 
    o.handler = h 
    o 
    end 

end 

So können Sie immer eine Instanz von MyClass haben, aber Sie haben eine Wegwerf-Kopie, die Spur seiner Geschichte hält. Dies ist vergleichbar mit cHao's Ansatz, aber es braucht keine zusätzliche Dekorator-Klasse, wie MyClass sich dekorieren kann.

1

Im Allgemeinen möchten Sie nicht (und in den meisten Fällen erhalten Sie nicht einmal wissen), wenn Ihre Methoden in einer bestimmten Weise aufgerufen werden. So liegt der Wahnsinn. Magic-Call-Sequenzen machen das Debuggen und Testen zu einem echten Kinderspiel.

Was Sie tun können, wenn ... statt mit do_a Rückkehr self, wickeln Sie ein Dekorateur um ihn herum, die do_b definiert, und gibt den Dekorateur. Zu diesem Zeitpunkt kann Ihr Original MyClass nicht do_b, weil es nicht wissen, wie. Aber das Ding konnte von do_a zurückkommen.

(Jetzt können Sie immer noch wie a = test.do_a sagen und dann a.do_b, aber Sie können um das nicht wirklich bekommen, ohne die Ruby-Code selbst parsen.)

0

Wie Chao sagte, Sie nicht zu Methodenaufruf versuchen sollte, Muster. Aber ich kann von einer anderen Weise denken auch, dies zu tun:

def do_a 
    puts "i just did a" 
    do_b_if_a(true) 
end 

def do_b_if_a(did_a=false) 
    puts "i just did b" if did_a 
end 

do_a  # prints "i just did a" 
do_b_if_a # does nothing 

Sicher, Sie können Anruf do_b_if_a(true), aber dann nur es macht sie flexibler;)

+0

Das Problem ist, ich muss immer noch Zugriff auf das Objekt haben. –

+0

Was meinst du, Zugriff auf das Objekt? – Jwosty

0

Bekommt man nicht den ganzen Weg da, aber man do_b_if_a als Singleton-Methode definieren könnte, die hinzugefügt wird, wenn to_a genannt wird:

class MyClass 

    def do_a 
    puts 'i just did a' 
    self.tap{|s| def s.do_b_if_a; puts 'i just did b' end} 
    end 

end 

Sie einen Blick auf Kernel.caller nehmen könnte, wenn Sie nehmen wollen bestimmte Aktionen basierend auf dem Aufruf-Stack. Sie könnten jedoch von einem anderen Entwickler ins Gesicht geschlagen werden, wenn Sie keinen guten Grund dafür haben, lol.

Verwandte Themen