Lors de l'appel d'une méthode, même si la méthode est définie dans sa propre classe Défini comme une méthode singulière dans une superclasse, un module ou une instance créée à partir d'une classe, etc. Je pense qu'il y a plusieurs cas. Cette fois, à propos du flux de recherche de méthode dans ces cas Je voudrais le résumer.
class Klass
def hello
puts "Hello_from_Klass"
end
end
klass_obj = Klass.new
klass_obj.hello
# => Hello_from_Klass
Cela semble être le cas le plus simple.
Lorsque la méthode hello
est appelée sur un objet obj
Naviguez jusqu'à la classe directe, la classe Klass, et recherchez la méthode hello
ici.
Dans ce cas, nous avons pu le trouver là, donc la recherche s'arrête là et la méthode est exécutée.
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
Pour la direction de recherche, référez-vous d'abord à la classe directe, et si elle n'y est pas
Cette classe parente, ou même cette classe parente ...
Est égal à l'ordre d'héritage des classes.
Dans ce cas, il faisait référence à «SubKlass» et il n'y avait pas de méthode «hello».
Parce que la méthode hello
a été définie en faisant référence à sa classe parente Klass
La recherche se termine et la méthode est exécutée.
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
Dans ce cas, au lieu de la méthode hello
définie dans la classe directe
La méthode hello
définie comme une méthode singulière a été appelée.
En d'autres termes, la classe singulière a sa méthode recherchée avant la classe de l'objet.
Je comprends.
Définir une méthode avec le même nom dans la super classe et le module Essayez d'appeler cette méthode à partir d'une instance d'une sous-classe.
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
La méthode hello
du module inclus a été appelée.
Le module inclus se situe entre la classe incluse et la classe parent.
Cela existera.
À ce stade, une classe anonyme qui semble envelopper le module est créée et intégrée dans l'arborescence d'héritage.
D'ailleurs, cette classe anonyme ne peut pas être touchée par les programmes Ruby.
Parce que la classe anonyme est créée et intégrée dans l'arborescence d'héritage de cette manière
La recherche de méthode peut être référencée par les mêmes règles que lorsque l'héritage normal est effectué.
Auparavant, je n'avais inclus qu'un seul module, le module include est différent de l'héritage de classe Vous pouvez inclure plusieurs modules pour une classe.
Incluons en fait plusieurs modules et appelons la méthode.
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
Lorsque plusieurs modules sont inclus La méthode du module qui a été inclus en dernier a été appelée. Lorsque plusieurs modules sont inclus dans la même classe de cette manière, Les modules sont incorporés dans l'arborescence d'héritage de cette classe dans l'ordre dans lequel ils sont inclus.
Premièrement, FirstModule est inclus et devient l'arbre d'héritage suivant.
Après cela, lorsque le SecondModule décrit ci-dessous est inclus, ce sera comme suit.
Cette fois, après avoir lu dans l'ordre de FirstModule``SecondModule
comme avant
Essayez à nouveau de charger FirstModule
.
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
La dernière description d'inclusion est FirstModule
C'est la méthode de SecondModule
qui a été appelée.
En fait, lors de l'insertion d'une classe qui encapsule un module dans l'arborescence d'héritage,
Vérification du même module dans l'arborescence d'héritage.
Par conséquent, lorsque le second "include First Module" est appelé,
Parce que FirstModule
est déjà inclus
La méthode include se termine sans être connectée.
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 inclut une classe anonyme qui encapsule un module
Alors qu'il est intégré au-dessus de la classe incluse
Le préfixe est intégré sous cette classe. (La méthode est appelée avec priorité sur la classe préparée)
Par conséquent, si vous appelez super
dans le module pour préparer,
La méthode portant le même nom dans la classe préfixe est appelée.
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)
J'ai essayé d'appeler la méthode bye
qui n'existe nulle part dans l'objet
Je crache «NoMethodError».
Lorsque la méthode bye est appelée, elle parcourt l'arborescence d'héritage afin de trouver la méthode.
Cependant, cette fois, il n'est défini nulle part, donc après une recherche en haut de l'arborescence d'héritage, BasicObject
Revenez à la classe directe SubKlass
, en recherchant cette fois la méthode method_missing
dans l'ordre de l'arborescence d'héritage.
Cette fois, c'est le plus haut niveau car je n'ai pas défini moi-même la méthode method_missing
La méthode method_missing
de BasicObject
est appelée pour déclencher une exception NoMethodError
.
Par conséquent, s'il y a une méthode method_midding
au milieu de l'arborescence d'héritage jusqu'à BasicObject
Appeler.
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}?Il n'y a pas de telle méthode"
end
end
class SubKlass < Klass
include HelloModule
end
obj = SubKlass.new
obj.bye
# => bye?Il n'y a pas de telle méthode
Comme flux de recherche
1, classe singulière de récepteur
2, classe directe
2 ', module si le module est inclus
3, 2 classes parents
3 ', module si le module est inclus
4, répétez 3
jusqu'à ce que la méthode soit trouvée
5, si vous ne recherchez pas en haut de l'arborescence d'héritage (BasicObject
), la recherche avec cette méthode se termine.
6, avec le nom de la méthode comme argument, recherchez la méthode method_missing
à partir de 1
7, Sinon, method_missing
de BasicObject
est appelé et une exception de NoMethodError
se produit.
Recommended Posts