ruby - objetos - Métodos de instancia en módulos.
modulo ruby (6)
La definición del módulo se evalúa como "esto es ...", ¿por qué?
En Ruby, todo es una expresión, no hay declaraciones o declaraciones. Lo que significa que todo se evalúa a un valor. (Sin embargo, esto no significa necesariamente que se evalúe como un valor útil . Por ejemplo, el método de puts
siempre se evalúa como nil
, al igual que una expresión de definición de método de definición (excepto en Rubinius, donde la expresión de def
evalúa como un objeto CompiledMethod
para siendo definido el método).
Por lo tanto, si todo se evalúa como un valor, ¿qué debería evaluar una expresión de definición de módulo? Bueno, hay un par de candidatos: podría evaluar hasta nil
, como una expresión de definición de método. O podría evaluar el objeto del módulo en sí, después de todo, esto es lo que estamos definiendo, ¿verdad? Pero en realidad, Matz eligió una tercera opción: las expresiones de definición de módulo (y clase) en realidad evalúan lo que la última expresión dentro del cuerpo de definición de módulo evalúa. (Esto le permite simular fácilmente las otras dos posibilidades simplemente colocando nil
o self
como la última expresión dentro de un cuerpo de definición de módulo).
En su caso, la última expresión dentro del cuerpo de definición del módulo es una asignación. Pero, ¿una asignación? ¿Qué diablos vuelve eso ? ¿No es eso una declaración? No, no en Ruby. Todo es una expresión, y las asignaciones no son una excepción: las expresiones de asignación se evalúan según lo que evalúe el lado derecho. Aquí, el lado derecho de la expresión de asignación es un literal de cadena, que se evalúa como un objeto de cadena.
Por lo tanto, toda la expresión de definición del módulo evalúa la cadena ''this is a const in module''
.
Considere el siguiente código:
module ModName
def aux
puts ''aux''
end
end
Si reemplazamos module
con class
, podemos hacer lo siguiente:
ModName.new.aux
Sin embargo, los módulos no pueden ser instanciados. ¿Hay alguna manera de llamar al método aux
en el módulo?
Piensa en lo que es aux
. ¿Qué objeto responderá a aux
? Es un método de instancia, lo que significa que las instancias de clases que incluyen ModName responderán a él. El módulo ModName en sí no es una instancia de dicha clase. Esto tampoco funcionaría si hubiera definido ModName como una clase; no puede llamar a un método de instancia sin una instancia.
Los módulos son muy parecidos a las clases que se pueden mezclar en otras clases para agregar comportamiento. Cuando una clase se mezcla en un módulo, todos los métodos de instancia del módulo se convierten en métodos de instancia de la clase. Es una forma de implementar herencia múltiple.
También sirven como sustitutos de los espacios de nombres, ya que cada módulo define un espacio de nombres. Pero eso es algo sin relación. (Por cierto, las clases también tienen sus propios espacios de nombres, pero convertirlas en una clase implica que crearás instancias de ellas, por lo que son conceptualmente erróneas para ese propósito).
Puedes hacerlo de esta manera:
module ModName
def aux
puts ''aux''
end
module_function :aux
end
y luego simplemente llámalo:
ModName.aux
También puede decir
module ModName
extend self
def aux
puts ''aux''
end
end
Luego puede incluir el módulo normalmente, pero también llamar a los métodos a través de ModName.
Y un poco más ...
module Y
def Y.a
puts "a"
end
def Y.b
c
end
def self.c
puts "b -- c"
end
end
llamada (sin ''.new''):
Y.a #=> "a"
Y.b #=> "b -- c"
Y.c #=> "b -- c"
class Foo
include ModName
end
Foo.new.aux
# output: aux