Ruby Language
Bericht overslaan
Zoeken…
Invoering
In Object Oriented Design ontvangen objecten berichten en beantwoorden deze. In Ruby roept het verzenden van een bericht een methode op en het resultaat van die methode is het antwoord.
In Ruby is het doorgeven van berichten dynamisch. Wanneer een bericht binnenkomt in plaats van precies te weten hoe te antwoorden, gebruikt Ruby een vooraf gedefinieerde set regels om een methode te vinden die erop kan antwoorden. We kunnen deze regels gebruiken om het bericht te onderbreken en te beantwoorden, het naar een ander object te sturen of het te wijzigen onder andere acties.
Telkens wanneer een object een bericht ontvangt, controleert Ruby:
- Als dit object een singleton-klasse heeft en dit bericht kan beantwoorden.
- Zoekt de klasse van dit object en vervolgens de vooroudersketen van de klasse.
- Een voor een controleert of er een methode beschikbaar is op deze voorouder en gaat deze hoger in de keten.
Boodschap passeren overerving keten
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
Om een geschikte methode te vinden voor SubExample#subexample_method
kijkt Ruby eerst naar de vooroudersketen van SubExample
SubExample.ancestors # => [SubExample, Example, Object, Kernel, BasicObject]
Het begint met SubExample
. Als we het bericht subexample_method
verzenden, kiest Ruby het beschikbare subexample en negeert Example#subexample_method
.
s.subexample_method # => :subexample
Na SubExample
het Example
. Als we sturen example_method
Ruby controleert of SubExample
kan beantwoorden of niet en omdat het kan niet Ruby gaat in de keten en kijkt in Example
.
s.example_method # => :example
Nadat Ruby alle gedefinieerde methoden heeft gecontroleerd, voert het method_missing
om te zien of het kan antwoorden of niet. Als we missing_subexample_method
verzenden, missing_subexample_method
Ruby geen gedefinieerde methode vinden op SubExample
dus gaat het naar Example
. Het kan ook geen gedefinieerde methode vinden op Example
of een andere klasse hoger in keten. Ruby begint opnieuw en voert method_missing
. method_missing
van SubExample
kan reageren op missing_subexample_method
.
s.missing_subexample_method # => :subexample
Als een methode echter is gedefinieerd, gebruikt Ruby een gedefinieerde versie, zelfs als deze hoger in de keten is. Als we bijvoorbeeld not_missed_method
verzenden, hoewel method_missing
van SubExample
kan reageren, loopt Ruby naar SubExample
omdat het geen gedefinieerde methode heeft met die naam en kijkt naar Example
dat er een heeft.
s.not_missed_method # => :example
Bericht passeren van modulesamenstelling
Ruby gaat omhoog naar de vooroudersketen van een object. Deze keten kan zowel modules als klassen bevatten. Dezelfde regels voor het opschuiven van de keten gelden ook voor modules.
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
Onderbrekende berichten
Er zijn twee manieren om berichten te onderbreken.
- Gebruik
method_missing
om een niet-gedefinieerd bericht te onderbreken. - Definieer een methode in het midden van een ketting om de boodschap te onderscheppen
Na het onderbreken van berichten is het mogelijk om:
- Antwoord ze.
- Stuur ze ergens anders naartoe.
- Wijzig het bericht of het resultaat.
Onderbreken via method_missing
en beantwoorden van bericht:
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
Bericht onderscheppen en wijzigen:
class Example
def initialize title, body
end
end
class SubExample < Example
end
Laten we ons nu eens voorstellen dat onze gegevens "title: body" zijn en dat we ze moeten splitsen voordat we Example
aanroepen. We kunnen initialize
definiëren op SubExample
.
class SubExample < Example
def initialize raw_data
processed_data = raw_data.split ":"
super processed_data[0], processed_data[1]
end
end
Bericht wordt onderschept en naar een ander object verzonden:
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