Oui, la méthode de recherche dans Ruby fonctionne un peu différemment de la méthode de recherche dans Python.
Le TL; DR réponse est, si vous voulez vraiment tirer la méthode length
du Array
objet de classe, vous aurez besoin d'écrire Array.instance_method(:length)
. Cela vous obtenir un objet UnboundMethod
, que vous pouvez ensuite lier à objet particulier et appeler:
unbound_method = Array.instance_method(:length)
ary = [1,2,3,4]
bound_method = unbound_method.bind(ary)
bound_method.call #=> 4
Sans surprise, ce n'est pas fait couramment dans Ruby.
Dans Ruby, les classes elles-mêmes sont des objets, instances de la classe Class
; ces classes ont leurs propres méthodes, au-dessus et au-delà des méthodes qu'ils fournissent à leurs instances, des méthodes telles que new
, name
, superclass
, etc. Bien sûr, il serait possible de définir une méthode length
sur l'objet de classe Array
de sorte que vous pourrait écrire Array.length
, mais cela ne serait pas intrinsèquement lié à la méthode d'instance du même nom. Il y a quelques endroits dans les classes de base et la bibliothèque standard où cela est réellement fait, mais pour la plupart, ce n'est pas idiomatique dans Ruby.
La distinction entre les méthodes d'un objet Class
répond directement, et celles qu'il prévoit ses instances, on peut voir assez clairement dans la sortie des méthodes methods
et instance_methods
:
irb(main):001:0> Array.methods
=> [:[], :try_convert, :new, :allocate, :superclass, ...
irb(main):002:0> Array.instance_methods
=> [:each_index, :join, :rotate, :rotate!, :sort!, ...
Une raison pour laquelle La méthode de recherche dans Ruby ne fonctionne pas comme elle le fait dans Python, car il peut y avoir des noms de méthodes auxquels une classe et une instance doivent répondre, de différentes manières. Par exemple, considérons une classe hypothétique Personne:
Person.ancestors # => [Person, Animal, Organism, Object, Kernel, BasicObject]
john = Person.new(...)
john.ancestors # => [John Sr., Sally, Jospeh, Mary, Charles, Jessica]
En Python, bien sûr, le premier appel serait une erreur: vous ne pouvez pas appeler Person.ancestors
sans passer une instance de Person
être __self__
, qui ne serait pas ne veut rien dire. Mais alors, comment obtenez-vous les ancêtres de la classe Person? Vous passeriez Person
lui-même à une fonction: inspect.getmro(Person)
. C'est idiomatique en Python, mais serait considéré comme un style extrêmement pauvre en Ruby. Essentiellement, en tant que langues différentes, même si elles sont similaires à bien des égards, elles ont toujours différentes façons de résoudre certains problèmes, et certaines choses qui sont considérées comme une bonne pratique ou un style sont très mauvaises dans l'autre (et vice versa).