[Ruby] Examinons l'arbre d'héritage tout en observant le flux de recherche de méthode

introduction

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.

Propre méthode

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.

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

Méthode de super classe

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.

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

Méthode singulière

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.

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

Méthodes mélangées dans la classe

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é.

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

Inclure plusieurs modules

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. スクリーンショット 2020-11-15 14.18.27.png

Après cela, lorsque le SecondModule décrit ci-dessous est inclus, ce sera comme suit. スクリーンショット 2020-11-15 14.20.11.png

Après avoir inclus le module, insérez-le à nouveau

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 de préfixe

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.

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

Appeler une méthode qui n'existe pas sur l'objet

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

Sommaire

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.

fin

Recommended Posts

[Ruby] Examinons l'arbre d'héritage tout en observant le flux de recherche de méthode
Examinez les éléments du tableau à l'aide de la méthode [Ruby] includes?
[Ruby] Imbrication de classes, héritage et principes de base de soi
définition de la méthode ruby
[Ruby] Questions et vérification du nombre d'arguments de méthode