Ruby Language
Message Passing
Suche…
Einführung
Im objektorientierten Design empfangen Objekte Nachrichten und antworten darauf. In Ruby wird durch das Senden einer Nachricht eine Methode aufgerufen, und das Ergebnis dieser Methode ist die Antwort.
In Ruby ist die Nachrichtenübergabe dynamisch. Wenn eine Nachricht ankommt, anstatt genau zu wissen, wie sie darauf antworten soll, verwendet Ruby vordefinierte Regeln, um eine Methode zu finden, die darauf antworten kann. Wir können diese Regeln verwenden, um die Nachricht zu unterbrechen und zu beantworten, an ein anderes Objekt zu senden oder sie unter anderen Aktionen zu ändern.
Jedes Mal, wenn ein Objekt eine Nachricht erhält, prüft Ruby:
- Wenn dieses Objekt über eine Singleton-Klasse verfügt, kann es auf diese Nachricht antworten.
- Sucht die Klasse dieses Objekts und die Vorfahrenkette der Klasse nach.
- Nacheinander wird geprüft, ob eine Methode für diesen Vorfahren verfügbar ist, und die Kette wird nach oben verschoben.
Nachricht, die die Vererbungskette durchläuft
class Example
def example_method
:example
end
def subexample_method
:example
end
def not_missed_method
:example
end
def method_missing name
return :example if name == :missing_example_method
return :example if name == :missing_subexample_method
return :subexample if name == :not_missed_method
super
end
end
class SubExample < Example
def subexample_method
:subexample
end
def method_missing name
return :subexample if name == :missing_subexample_method
return :subexample if name == :not_missed_method
super
end
end
s = Subexample.new
Um eine geeignete Methode für SubExample#subexample_method
zu finden, SubExample#subexample_method
Ruby zunächst die Vorfahrenkette von SubExample
SubExample.ancestors # => [SubExample, Example, Object, Kernel, BasicObject]
Es beginnt mit SubExample
. Wenn wir eine subexample_method
Nachricht senden, subexample_method
Ruby das verfügbare SubExample aus und ignoriert Example#subexample_method
.
s.subexample_method # => :subexample
Nach SubExample
wird Example
überprüft. Wenn wir example_method
senden, example_method
Ruby, ob SubExample
darauf antworten kann oder nicht und da Ruby nicht kann, geht Ruby die Kette hoch und sucht nach Example
.
s.example_method # => :example
Nachdem Ruby alle definierten Methoden method_missing
, führt es method_missing
zu sehen, ob es antworten kann oder nicht. Wenn wir missing_subexample_method
senden, missing_subexample_method
Ruby keine definierte Methode in SubExample
sodass es zu Example
. Es kann auch keine definierte Methode in Example
oder einer anderen höheren Klasse in der Kette finden. Ruby beginnt erneut und führt method_missing
. method_missing
of SubExample
kann auf missing_subexample_method
antworten.
s.missing_subexample_method # => :subexample
Wenn eine Methode definiert ist, verwendet Ruby die definierte Version, auch wenn sie in der Kette höher ist. Wenn wir beispielsweise not_missed_method
senden, obwohl method_missing
von SubExample
darauf antworten kann, geht Ruby auf SubExample
da es keine definierte Methode mit diesem Namen hat und Example
mit einem Example
sucht.
s.not_missed_method # => :example
Nachricht, die durch die Modulzusammensetzung geht
Ruby bewegt sich in der Ahnenkette eines Objekts auf. Diese Kette kann sowohl Module als auch Klassen enthalten. Die gleichen Regeln für das Hochfahren der Kette gelten auch für Module.
class Example
end
module Prepended
def initialize *args
return super :default if args.empty?
super
end
end
module FirstIncluded
def foo
:first
end
end
module SecondIncluded
def foo
:second
end
end
class SubExample < Example
prepend Prepended
include FirstIncluded
include SecondIncluded
def initialize data = :subexample
puts data
end
end
SubExample.ancestors # => [Prepended, SubExample, SecondIncluded, FirstIncluded, Example, Object, Kernel, BasicObject]
s = SubExample.new # => :default
s.foo # => :second
Nachrichten unterbrechen
Es gibt zwei Möglichkeiten, Nachrichten zu unterbrechen.
- Verwenden Sie
method_missing
um eine nicht definierte Nachricht zu unterbrechen. - Definieren Sie eine Methode in der Mitte einer Kette, um die Nachricht abzufangen
Nach dem Unterbrechen von Nachrichten ist es möglich:
- Antworte ihnen.
- Schicke sie woanders hin.
- Ändern Sie die Nachricht oder das Ergebnis.
Unterbrechen über method_missing
und Beantworten der Nachricht:
class Example
def foo
@foo
end
def method_missing name, data
return super unless name.to_s =~ /=$/
name = name.to_s.sub(/=$/, "")
instance_variable_set "@#{name}", data
end
end
e = Example.new
e.foo = :foo
e.foo # => :foo
Nachricht abfangen und ändern:
class Example
def initialize title, body
end
end
class SubExample < Example
end
Lassen Sie sich nun vorstellen , unsere Daten „Titel: Körper“ und wir haben sie zu spalten vor dem Aufruf Example
. Wir können initialize
für SubExample
definieren.
class SubExample < Example
def initialize raw_data
processed_data = raw_data.split ":"
super processed_data[0], processed_data[1]
end
end
Nachricht abfangen und an ein anderes Objekt senden:
class ObscureLogicProcessor
def process data
:ok
end
end
class NormalLogicProcessor
def process data
:not_ok
end
end
class WrapperProcessor < NormalLogicProcessor
def process data
return ObscureLogicProcessor.new.process data if data.obscure?
super
end
end