2016-01-17 11 views
6

Was ist der Zweck von Method#unbind und UnboundMethod#bind?Was ist der Zweck von Bind/Unbind-Methoden in Ruby?

Von dem, was ich sammle, Methoden sind aufrufbar Objekte wie Procs und Lambda, mit der Ausnahme, dass Methoden auf den Umfang ihres Empfängers gebunden sind:

class SomeClass 
    def a_method; puts "from SomeClass"; end 
end 

s = SomeClass.new 
s.a_method # => "from SomeClass" 

Ich kann a_method anrufen, wenn ich im Rahmen der SomeClass bin oder wenn ich ein Objekt von SomeClass habe. Ich kann es ein aufrufbare Objekt, indem Sie das Verfahren als Method Objekt zu extrahieren, aber es ist immer noch auf ein Objekt der Klasse SomeClass in diesem Beispiel gebunden:

m = s.method :a_method 
m.class # => Method 
m.owner # => SomeClass 
m.call # => "from SomeClass" 

Warum sollte ich will unbind eine Methode aus seinem Empfänger? Vielleicht kann ich dies um oder bind es zu einem anderen Objekt übergeben gibt es neuen Kontext, vielleicht kann ich ein völlig anderes Objekt diese Methode ohne Vererbung aufrufen, aber ich kann nichts damit tun, es sei denn ich es an ein Objekt seiner binden Original-Klasse oder ich wandeln es in ein Proc Objekt (wirklich eine Lambda, da Methoden und Lambda-Ausdrücke sind etwas ähnlich):

# Module#instance_method gives me an UnboundMethod 
ub = SomeClass.instance_method :a_method 
ub.class # -> UnboundMethod 

# now I can't make any calls 
ub.call # -> NoMethod Error, undefined method 'call' 

class AnotherClass; end 
a = AnotherClass.new 
b = ub.bind(a) # -> TypeError: bind argument must be an instance of SomeClass 
b = ub.bind(SomeClass.new).call # -> "from SomeClass" 

ich konnte das Verfahren Objekt in ein proc konvertieren und vielleicht etwas mit ihm tun:

AnotherClass.class_eval do 
    # I can access m becausec this block is evaluated in the same 
    # scope it's defined, so I can grab m ;) 
    define_method(:method_from_some_class, m.to_proc) 
end 

AnotherClass.instance_methods(false) # -> [:method_from_some_class] 
a.method_from_some_class # -> "from SomeClass" 

Was ist der Zweck, dies zu tun? Was sind die realen Anwendungen für so etwas?

+0

Welp ... http://stackoverflow.com/questions/33708250/what-is-the-point-of-rubys-method-unbinding-mechanism – ndn

+1

Ich verstehe, was sie tun, aber ich werde das sagen 8 Jahre Ruby-Programmierung, einschließlich gelegentlicher reflektierender Metaprogrammierungsklugheit, ich musste nie 'bind' auf einer ungebundenen Methode verwenden oder viel mit einer ungebundenen Methode überhaupt tun. Sie werden selten benötigt. Aber gut, dass sie für eine komplette reflektierende Kontrolle in Ruby da sind. Wenn Sie keine Verwendung für sie sehen, ist es, weil die Verwendungen für knifflige Dinge selten sind, die Sie wissen werden, wenn Sie einen haben. Wenn es Teil Ihrer täglichen Toolbox ist, sind Sie wahrscheinlich viel zu schlau. – jrochkind

Antwort

6

Es ist in der Tat nützlich für Metaprogrammierung. Angenommen, Sie möchten wissen, wo sich der Quellcode für SomeClass#method befindet. Wenn Sie eine Instanz von SomeClass generieren können, können Sie eine (gebundene) Methodeninstanz davon in der Instanz SomeClass erstellen, auf der Sie verschiedene Methoden aufrufen können, um einige Metadaten der Methode zu untersuchen. Aber was ist, wenn Sie die Methodensignatur von SomeClass#new nicht kennen, oder was ist, wenn die Konstruktormethode SomeClass anders als SomeClass#new benannt wurde? Nur eine Instanz von SomeClass sicher erstellen kann schwierig sein. Das ist, wo ungebundene Methode nützlich ist. Ohne sich mit einer bestimmten Instanz der Klasse oder mit dem Erstellen einer Instanz zu beschäftigen, können Sie einfach SomeClass.instance_method(:a_method) (die eine ungebundene Methode ist) ausführen und dann source_location darauf aufrufen, um den Speicherort der Definition zu untersuchen.

Und wann wäre diese Art von Metaprogrammierung in den realen Anwendungen notwendig? Ein Beispiel ist, wenn Sie eine IDE mit Funktionen für die Methoden-Suche erstellen.