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:

  1. Wenn dieses Objekt über eine Singleton-Klasse verfügt, kann es auf diese Nachricht antworten.
  2. Sucht die Klasse dieses Objekts und die Vorfahrenkette der Klasse nach.
  3. 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


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow