D'après ce que je comprends, le mot clé super
invoque une méthode portant le même nom que la méthode actuelle dans la superclasse de la classe actuelle. Ci-dessous dans la méthode autoload
, il y a un appel à super
. Je voudrais savoir dans quelle superclasse je trouverais une méthode du même nom ou que fait l'appel à super
ici
module ActiveSupport
module Autoload
...
def autoload(const_name, path = @@at_path)
full = [self.name, @@under_path, const_name.to_s, path].compact.join("::")
location = path || Inflector.underscore(full)
if @@eager_autoload
@@autoloads[const_name] = location
end
super const_name, location
end
....
end
end
module ActiveRecord
extend ActiveSupport::Autoload
...
autoload :TestCase
autoload :TestFixtures, 'active_record/fixtures'
end
Ce code provient de la branche principale Rails. Merci beaucoup.
super
:module Vehicular
def move_forward(n)
@position += n
end
end
class Vehicle
include Vehicular # Adds Vehicular to the lookup path
end
class Car < Vehicle
def move_forward(n)
puts "Vrooom!"
super # Calls Vehicular#move_forward
end
end
puts Car.ancestors.inspect
# Output
# [Car, Vehicle, Vehicular, Object, Kernel, BasicObject]
Notez l'inclusion de l'objet Vehicular
Module
!
Cochez objRef.class.ancestors
Ou ClassName.ancestors
Pour connaître la chaîne d'héritage. Si la super classe ne contient pas la méthode, tous les modules inclus par la super classe sont vérifiés (le dernier inclus est vérifié en premier). Si aucun match, il monte d'un niveau à la classe des grands-parents et ainsi de suite.
Vous pouvez utiliser la liste des ancêtres, puis appeler AncestorClass.methods.select{|m| m.include?("auto_load")}
pour vous concentrer sur la méthode appelée.
(Remarque: le code ci-dessus est Ruby 1.8. Dans 1.9 methods
renvoie des symboles au lieu de chaînes. Vous devez donc faire un m.to_s.include?(...
))
Utilisez Pry
Insérez un binding.pry
appelez juste avant d'utiliser super
, puis appelez show-source -s
(-s
signifie superclass
) pour afficher la méthode de la superclasse et savoir où elle est définie:
class A
def hello
puts "hi"
end
end
class B < A
def hello
binding.pry
super
end
end
b = B.new
b.hello
From: (pry) @ line 7 B#hello:
7: def hello
=> 8: binding.pry
9: super
10: end
[1] (pry) #<B>: 0> show-source -s
From: (pry) @ line 2:
Number of lines: 3
Owner: A # <--see owner here (i.e superclass)
Visibility: public
def hello
puts "hi"
end
[2] (pry) #<B>: 0>
Le mot clé super
vérifie tout le long de l'arbre d'ascendance pour trouver la méthode héritée.
Effectuez une recherche sur l'ensemble de la branche principale Rails. Vous ne trouverez qu'une seule def autoload
qui est exactement celui que vous regardez dans active_support/lib/active_support/dependencies/autoload.rb
.
La méthode en cours de substitution est Ruby native. C'est Module#autoload
J'ai ajouté cette méthode pour trouver le propriétaire d'une méthode dans mon .irbrc, quelqu'un voit-il une meilleure façon de le faire, en particulier dans la gestion des méthodes singleton où la superclasse de la classe singleton est la classe singleton de la superclasse?
class Object
def find_method(method_string)
if klasses = self.class.ancestors.select { |a| a if a.methods.include? method_string }
puts "class method in #{klasses.join(',')}" unless klasses.empty?
end
if klasses = self.class.ancestors.select { |a| a if a.instance_methods.include? method_string }
puts "instance method in #{klasses.join(',')}" unless klasses.empty?
end
rescue
raise "owning class not found"
end
end
La méthode de superclasse appropriée est probablement Module # autoload .