[Ruby] Untersuchen wir den Vererbungsbaum, während wir den Ablauf der Methodensuche beobachten

Einführung

Beim Aufrufen einer Methode, auch wenn die Methode in einer eigenen Klasse definiert ist Definiert als singuläre Methode in einer Oberklasse, einem Modul oder einer Instanz, die aus einer Klasse usw. erstellt wurde. Ich denke, es gibt verschiedene Fälle. Diesmal über den Ablauf der Methodensuche in diesen Fällen Ich möchte es zusammenfassen.

Eigene Methode

class Klass
  def hello
    puts "Hello_from_Klass"
  end
end

klass_obj = Klass.new
klass_obj.hello
# => Hello_from_Klass

Es scheint der einfachste Fall zu sein. Wenn die "Hallo" -Methode für ein "obj" -Objekt aufgerufen wird Navigieren Sie zur direkten Klasse, der Klass-Klasse, und suchen Sie dort nach der "Hallo" -Methode. In diesem Fall konnten wir es dort finden, sodass die Suche dort endet und die Methode ausgeführt wird.

スクリーンショット 2020-11-14 22.35.18.png

Super Klasse Methode

class Klass
  def hello
    puts "Hello from Klass"
  end
end

class SubKlass < Klass
end

sub_klass_obj = SubKlass.new
sub_klass_obj.hello
# => Hello_from_Klass

Beziehen Sie sich für die Suchrichtung zuerst auf die direkte Klasse, und wenn sie nicht vorhanden ist Diese Elternklasse oder sogar diese Elternklasse ... Ist gleich der Vererbungsreihenfolge der Klassen. In diesem Fall bezog es sich auf "SubKlass" und es gab keine "Hallo" -Methode. Weil die "Hallo" -Methode unter Bezugnahme auf die übergeordnete Klasse "Klass" definiert wurde Die Suche endet und die Methode wird ausgeführt.

スクリーンショット 2020-11-14 22.50.48.png

Singuläre Methode

class Klass
  def hello
    puts "Hello from Klass"
  end
end

obj = Klass.new

def obj.hello
  puts "Hello from singleton"
end

obj.hello
# => Hello from singleton

In diesem Fall anstelle der in der direkten Klasse definierten "Hallo" -Methode Die als singuläre Methode definierte "Hallo" -Methode wurde aufgerufen. Mit anderen Worten, die Methode der Singularklasse wird vor der Klasse des Objekts gesucht. Ich verstehe.

スクリーンショット 2020-11-15 13.31.57.png

Methoden in die Klasse gemischt

Definieren Sie eine gleichnamige Methode in der Superklasse und im Modul Versuchen Sie, diese Methode von einer Instanz einer Unterklasse aus aufzurufen.

module HelloModule
  def hello
    puts "Hello from HelloModule"
  end
end

class Klass
  def hello
    puts "Hello from Klass"
  end
end

class SubKlass < Klass
  include HelloModule
end


sub_klass_obj = SubKlass.new
sub_klass_obj.hello
# => Hello from HelloModule

Die "Hallo" -Methode des enthaltenen Moduls wurde aufgerufen. Das eingeschlossene Modul liegt zwischen der eingeschlossenen Klasse und der übergeordneten Klasse. Es wird existieren. Zu diesem Zeitpunkt wird eine anonyme Klasse erstellt und in den Vererbungsbaum eingebettet, die das Modul zu umschließen scheint. Diese anonyme Klasse kann übrigens nicht von Ruby-Programmen berührt werden.  Weil die anonyme Klasse auf diese Weise erstellt und in den Vererbungsbaum eingebettet wird Auf die Methodensuche kann nach denselben Regeln verwiesen werden wie bei der normalen Vererbung.

スクリーンショット 2020-11-15 14.03.40.png

Schließen Sie mehrere Module ein

Früher habe ich nur ein Modul aufgenommen, Modul Include unterscheidet sich von Klassenvererbung Sie können mehrere Module für eine Klasse einschließen.

Lassen Sie uns tatsächlich mehrere Module einschließen und die Methode aufrufen.

module FirstModule
  def hello
    puts "Hello from FirstModule"
  end
end

module SecondModule
  def hello
    puts "Hello from SecondModule"
  end
end

class Klass
  def hello
    puts "Hello from Klass"
  end
end

class SubKlass < Klass
  include FirstModule
  include SecondModule
end


sub_klass_obj = SubKlass.new
sub_klass_obj.hello
# => Hello from SecondModule

Wenn mehrere Module enthalten sind Die Methode des zuletzt enthaltenen Moduls wurde aufgerufen. Wenn auf diese Weise mehrere Module in derselben Klasse enthalten sind, Module werden in der Reihenfolge, in der sie enthalten sind, in den Vererbungsbaum dieser Klasse eingebettet.

Erstens ist FirstModule enthalten und wird zum folgenden Vererbungsbaum. スクリーンショット 2020-11-15 14.18.27.png

Wenn danach das unten beschriebene zweite Modul enthalten ist, sieht es wie folgt aus. スクリーンショット 2020-11-15 14.20.11.png

Fügen Sie das Modul nach dem Einfügen erneut hinzu

Diesmal nach dem Lesen in der Reihenfolge FirstModule``SecondModule wie zuvor Versuchen Sie erneut, FirstModule zu laden.

 module FirstModule
  def hello
    puts "Hello from FirstModule"
  end
end

module SecondModule
  def hello
    puts "Hello from SecondModule"
  end
end

class Klass
  def hello
    puts "Hello from Klass"
  end
end

class SubKlass < Klass
  include FirstModule
  include SecondModule
  include FirstModule
end


sub_klass_obj = SubKlass.new
sub_klass_obj.hello
# => Hello from SecondModule

Die letzte Include-Beschreibung lautet "FirstModule" Es war die Methode von "SecondModule", die aufgerufen wurde.

Wenn Sie eine Klasse einfügen, die ein Modul in den Vererbungsbaum einschließt, Suchen im Vererbungsbaum nach demselben Modul. Wenn daher das zweite "Include First Module" aufgerufen wird, Weil FirstModule bereits enthalten ist Die include-Methode endet, ohne eingesteckt zu sein.

Modul voranstellen

module PrependModule
  def hello
    puts "Hello from PrependModule"
  end
end

module IncludeModule
  def hello
    puts "Hello from IncludeModule"
  end
end

class Klass
  prepend PrependModule
  include IncludeModule
  def hello
    puts "Hello from Klass"
  end
end

klass_obj = Klass.new
klass_obj.hello
# => Hello from PrependModule

include enthält eine anonyme Klasse, die ein Modul umschließt Während es über der eingeschlossenen Klasse eingebettet ist Das Präfix ist unterhalb dieser Klasse eingebettet. (Die Methode wird mit Priorität vor der vorbereiteten Klasse aufgerufen.) Wenn Sie daher im Modul "super" aufrufen, um sich vorzubereiten, Die gleichnamige Methode in der Prepend-Klasse wird aufgerufen.

スクリーンショット 2020-11-15 16.51.41.png

Rufen Sie eine Methode auf, die für das Objekt nicht vorhanden ist

module HelloModule
  def hello
    puts "Hello from FirstModule"
  end
end

class Klass
  def hello
    puts "Hello from Klass"
  end
end

class SubKlass < Klass
  include HelloModule
end

obj = SubKlass.new
obj.bye
# => undefined method `bye' for #<SubKlass:0x00007fb5fb80c628> (NoMethodError)

Ich habe versucht, die "bye" -Methode aufzurufen, die nirgendwo im Objekt vorhanden ist Ich spucke "NoMethodError" aus.

Wenn die bye-Methode aufgerufen wird, durchläuft sie den Vererbungsbaum, um die Methode zu finden. Diesmal ist es jedoch nirgendwo definiert, also nach der Suche an der Spitze des Vererbungsbaums "BasicObject" Kehren Sie zur direkten Klasse "SubKlass" zurück und suchen Sie diesmal nach der Methode "method_missing" in der Reihenfolge des Vererbungsbaums. Diesmal ist es die höchste Ebene, da ich die Methode "method_missing" nicht selbst definiert habe Die Methode method_missing von BasicObject wird aufgerufen, um als Ausnahme einen NoMethodError auszulösen.

Wenn sich also in der Mitte des Vererbungsbaums eine method_midding -Methode befindet, bis zu BasicObject Nennen.

module HelloModule
  def hello
    puts "Hello from FirstModule"
  end
end

class Klass
  def hello
    puts "Hello from Klass"
  end

  def method_missing(method_name, *args)
    puts "#{method_name}?Es gibt keine solche Methode"
  end
end

class SubKlass < Klass
  include HelloModule
end

obj = SubKlass.new
obj.bye
# => bye?Es gibt keine solche Methode

Zusammenfassung

Als Suchfluss 1, singuläre Empfängerklasse 2, direkte Klasse 2 ', Modul, wenn Modul enthalten ist 3, 2 Elternklassen 3 ', Modul, wenn Modul enthalten ist 4, Wiederholen Sie "3", bis die Methode gefunden wird 5, Wenn Sie nicht zum Anfang des Vererbungsbaums (BasicObject) suchen, endet die Suche mit dieser Methode. 6, Suchen Sie mit dem Methodennamen als Argument nach der Methode method_missing von 1 7, Wenn nicht, wird method_missing von BasicObject aufgerufen und eine Ausnahme von NoMethodError tritt auf.

Ende

Recommended Posts

[Ruby] Untersuchen wir den Vererbungsbaum, während wir den Ablauf der Methodensuche beobachten
Untersuchen Sie die Elemente im Array mit der Methode [Ruby] include?
[Ruby] Klassenverschachtelung, Vererbung und die Grundlagen des Selbst
Definition der Rubinmethode
[Ruby] Fragen und Überprüfung der Anzahl der Methodenargumente