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.
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.
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.
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.
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.
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.
Wenn danach das unten beschriebene zweite Modul enthalten ist, sieht es wie folgt aus.
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.
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.
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
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.
Recommended Posts