Ruby en línea:
https://paiza.io/projects/3P-5xOa5TfPscvm1Npj98g?language=ruby
https://www.youtube.com/watch?v=9nZGCEX2bi4
==================================================================
En Ruby todo es un objeto, y los módulos son una clase especial que no puede instanciarse a sí misma, es una clase muy limitada que permite que desde fuera de ella se pueda llamar a su contenido.
Este llamamiento puede ser en dos direcciones, por un lado para añadir funcionalidad a las instancias de otras clases o para añadir funcionalidad a otras clases pero no a sus instancias.
Cuando se utiliza para añadir funcionalidad a las instancias, se utiliza la instrucción
include que viene a significar, incluye el módulo en esta clase para dotar a las instancias esas características.
Cuando se utiliza con la instrucción
extend, lo que se hace es extender con el contenido del módulo las variables de clase, pero no de sus instancias. Cuando se utiliza extend siempre se refiere a su propio objeto self, pues no es utilizable a ninguna de las instancias que se crean desde la clase.
Como su nombre indica, los módulos son construcciones modulares para hacer cosas o para tener a la mano su contenido, estas cosas solo son parámetros que pueden ser llamadas desde otros métodos, clases e instancias.
Pueden contener de todo; constantes, variables, métodos y clases.
Una forma de verlos es como una librería donde dejar una serie de variables, constantes, métodos y/o clases que pueden ser útiles desde fuera del módulo, quizá para no estar repitiendo código más a delante.
Su sintáxis es:
module Nombredelmódulo #empieza en mayúscula
.
.
.
end
Pueden estar escritos en el mismo fichero que el resto del programa, para lo cual han de ir antes de aquello que lo invoque y la manera de invocarlo es:
include Nombredelcontenidodelmodulo
y dentro del código n.nombremétododelmódulo
o
extend Nombredelcontenidomodulo
Así:
module Prueba
puts "Esto es una prueba"
end
include Prueba # o extend Prueba
Pero, también pueden ser ficheros de ruby aparte a los que se les invoca desde otro fichero ruby, de manera que habrá que utilizar al inicio del programa que lo va a necesitar. La invocación se realiza con la sentencia
require_relative "nombredel fichero.rb"
Hay que tener en cuenta que require_relative es una sentencia que indica que el fichero está en el mismo directorio desde donde se está ejecutando el que lo llama, de lo contrario habría que poner su ruta con
require sin _relative, así, por ejemplo:
require "c:/nombredefichero.rb"
Veamos poco a poco el tema de acceso a los módulos.
INCLUDE:
utilizamos include cuando queremos incluir su código en el código que lo necesita, amplía los métodos con los de los métodos.
Las instancias llaman a los métodos de los módulos.
h = Instancia.new
h.métododelmódulo
Veamos un ejemplo:
En este caso vamos a añadir una frase a un método, sólo podemos hacerlo mediante la clase self, pues no hay clase definida e include sólo actúa sobre una instancia de una clase, en Ruby siempre hay un Object sobre el que recae todo.
module Prueba
puts "Esto es una prueba"
end
def Accion
include Prueba #también podríamos escribir exten Prueba
end
self
puts self.class
Da la salida:
Esto es una prueba
Object
Como vemos, self es de la clase Objet y es sobre el que recae la acción.
Ahora vamos a mezclar módulos y clases, a esto se le llama mixin.
module Saludar
puts 'Este es mi saludo'
end
module Despedida
puts 'Ahora me despido'
class Persona
include Saludar
puts 'Hoooooola'
include Despedida
end
Ésto da la salida:
Este es mi saludo # al entrar en la clase se salta al módulo Saludar y después vuelve a la clase
Ahora me despido # ejecuta el otro módulo Despedida y regresa a la clase
Hoooooola
Nótese que los módulos que encuentre en la clase los ejecuta antes de continuar con la clase.
Bien, si tenemos varias clases, el método estará disponible a todas ellas siempre que se invoque fuera de ellas, si no es así, sólo será accesible desde la clase en la que esté invocado.
A su vez, dentro de la clase que lo invoca, no puede estar dentro de un método de su clase, siempre fuera de cualquier método entre el class Nombrecalse y su correspondiente end.
Si el método contiene método/s, entonces las instancias de la clase que lo invoque tendrá acceso a ello/s como si fuera suyo.
Veamos un ejemplo:
module Lenguaje
def idioma
puts 'Inglés'
end
end
module Ladrido
def ladrido
puts "Guau Guau Guau"
end
end
class Persona
include Lenguaje
def initialize
end
def nombre
puts "Eres persona con lenguaje "
end
end
class Perro
def initialize
end
include Ladrido
def nombre_perro
puts "soy un Chucho y digo "
end
end
h = Persona.new
h.nombre
h.idioma
p = Perro.new
p.nombre_perro
p.ladrido
la salida es:
Eres persona con lenguaje
Inglés
soy un Chucho y digo
Guau Guau Guau
Ni el p puede invocar el método nombre ni h el método ladrido, daría error.
imaginemos que el módulo Saludar está en un fichero llamado saludar.rb y el módulo Ladrido en otro llamado ladrar.rb, entonces el código quedaría así:
require_relative "saludar,rb"
require_relative "ladrar.rb"
class Persona
include Lenguaje
def initialize
end
def nombre
puts "Eres persona con lenguaje "
end
end
class Perro
def initialize
end
include Ladrido
def nombre_perro
puts "soy un Chucho y digo "
end
end
h = Persona.new
h.nombre
h.idioma
p = Perro.new
p.nombre_perro
p.ladrido
y daría la misma salida.
Al hecho de introducir un módulo dentro de una clase se llama mixins, como mezcla de cosas.
EXTEND:
Se utiliza cuando se añade el código que lo usa a la clase como métodos de clase.
Como los métodos de los módulos se convierten en métodos de clase se llamarán desde la clase, no desde sus instancias, así:
Nonbredelaclase.nombremétododelmódulo
Ejemplos:
module Terrestre
def circula
puts "Puedo ir por la tierra"
end
end
module Acuatico
def navega
puts "Puedo navegar por el agua"
end
end
class Vehiculo
extend Terrestre
extend Acuatico
def vehiculo
puts "soy un vehículo"
end
end
Vehiculo.circula
Vehiculo.navega
Da la salida:
Puedo ir por la tierra
Puedo navegar por el agua
Como se ve es la clase Vehiculo y no sus instancias quien puede acceder a los métodos de los módulos Terrestre y Acuatico.
Si pusiéramos include, habría que acceder a través de las instancias, así:
module Terrestre
def circula
puts "Puedo ir por la tierra"
end
end
module Acuatico
def navega
puts "Puedo navegar por el agua"
end
end
class Vehiculo
include Terrestre
include Acuatico
def vehiculo
puts "soy un vehículo"
end
end
h = Vehiculo.new
h.circula
h.navega
que dará la salida:
Puedo ir por la tierra
Puedo navegar por el agua
Que se refieren a la instancia h.
Por último, hay otra manera de acceder a los valores de un módulo y es mediante
::
Desde fuera del método, se puede acceder a sus variables, métodos y clases con invocarlas así:
nombredelmodulo::loquequeramos
Veamos un ejemplo.
module Terrestre
def self.circula # Hay que poner self porque se refiere a sí mismo
puts "Puedo ir por la tierra"
end
end
module Acuatico
def self.navega # Hay que poner self porque se refiere a sí mismo
puts "Puedo navegar por el agua"
end
end
module Constantes
A = 100
BG = 896
end
puts Terrestre::circula
puts Acuatico::navega
puts Constantes::BG
Esto nos da la salida:
Puedo ir por la tierra
Puedo navegar por el agua
896