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