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:

  1. Als dit object een singleton-klasse heeft en dit bericht kan beantwoorden.
  2. Zoekt de klasse van dit object en vervolgens de vooroudersketen van de klasse.
  3. 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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow