Pregunta
¿Cómo es que Ruby permite a una clase acceder a métodos fuera de la clase implícitamente?
Ejemplo:
class Candy
def land
homer
end
end
def homer
puts "Hello"
end
Candy.new.land #Outputs Hello
Solución
La definición del '' jonrón '' El método es agregar el método a la clase Object. No está definiendo una función libre.
Class Candy hereda implícitamente de Object y, por lo tanto, tiene acceso a los métodos de Object. Cuando llamas a "homer" en la "tierra" método, la resolución del método no puede encontrar una definición en la clase actual, va a la superclase, encuentra el método que ha agregado a Object y lo llama.
Otros consejos
Una forma sencilla de descubrir qué sucede
-
¿Qué clases / módulos se buscan para resolver los métodos utilizados en los objetos Candy?
p Candy.ancestors # = > [Dulces, Objetos, Kernel]
-
¿Candy tiene un método llamado jonrón?
p Candy.instance_methods (false) .grep (" homer ") # = > []
p Candy.private_instance_methods (false) .grep (" homer ") # = > []
-
Bien, Candy no tiene ningún método llamado 'homer'.
-
¿Qué sigue en la cadena de búsqueda (ver 1) = > " Objeto "
-
¿Tiene el objeto un método llamado " homer " ? p Object.instance_methods (false) .grep (" homer ") # = > []
p Object.private_instance_methods (false) .grep (" homer ") # = > [" homer "]
Candy tiene Object en su cadena de búsqueda, que a su vez tiene un método de instancia privada " homer " para que la resolución del método sea satisfactoria
La declaración de definición siempre define el método en la clase de lo que self esté en el punto de definición
-
¿Qué es self justo antes de definir el homer?
p self # = > principal def jonrón pone " Hola " fin
-
Entonces, ¿cuál es su tipo?
p self.class # = > Objeto
Por eso homer termina en Object
Técnicamente, la definición del método homer
está realmente en el módulo Kernel
que se mezcla en Object
, no en < código> Objeto directamente. Entonces, cuando homer
no es una variable local o un método de instancia definido en Candy
, la cadena de herencia del método Ruby se sigue a través de Object
y luego a se ejecuta el módulo Kernel
y luego se ejecuta este código.
Editar: Lo siento, no sé por qué pensé esto. Parece que el método realmente vive en Object
. No estoy seguro de que haya una gran diferencia en la práctica, pero debería haber confirmado las cosas antes de publicar.
Ruby no tiene funciones de flotación libre. Cada método pertenece a algún objeto. Los métodos que def
en el nivel superior se están convirtiendo en métodos de instancia de la clase Object
. Como todo es un Object
en algún nivel, todos los objetos tienen acceso a los métodos de instancia de Object
.