Module
que representa al módulo.
Say you write a set of the trigonometry functionssin
, cos, and so on. You stuff them all into a file,trig.rb
, for future generations to enjoy. Meanwhile, Sally is working on a simulation of good and evil, and she codes a set of her own useful routines, includingbe_good
andsin
, and sticks them intomoral.rb
. Joe, who wants to write a program to find out how many angels can dance on the head of a pin, needs to load bothtrig.rb
andmoral.rb
into his program. But both define a method calledsin
. Bad news.
The answer is the module mechanism. Modules define a namespace, a sandbox in which your methods and constants can play without having to worry about being stepped on by other methods and constants. The trig functions can go into one module:
Dave Thomas
module Trig PI = 3.141592654 def Trig.sin(x) # .. end def Trig.cos(x) # .. end end
# Sample code from Programing Ruby, page 111 module Moral VERY_BAD = 0 BAD = 1 def Moral.sin(badness) # ... end endIf a third program wants to use these modules, it can simply load the two files (using the Ruby require statement. In order to reference the name sin unambiguously, our code can then qualify the name using the name of the module containing the implementation we want, followed by::
, the scope resolution operator:
$: << '.' require 'trig' require 'moral' y = Trig.sin(Trig::PI/4) wrongdoing = Moral.sin(Moral::VERY_BAD)
Ejemplo: Codificar y Decodificar Datos Usando Base64
Supongamos que estamos un método para codificar y decodificar datos binarios utilizando la codificaciónBase64
. Puesto queencode
ydecode
son dos nombres muy comunes, para preveer colisiones de nombres definimos nuestros dos métodos dentro de un módulo:
casiano@exthost:~/rubytesting/TheRubyProgrammingLanguage/Chapter7ClassesAndModules/modules$ cat -n base64_mod_self.rb 1 module Base64 2 3 puts self # Base64 4 5 DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 6 'abcdefghijklmnopqrstuvwxyz' + 7 '0123456789+/' 8 @x = "hello" 9 10 def self.encode 11 "self.encode #@x" 12 end 13 14 def self.decode 15 "self.decode #@x" 16 end 17 end 18 if $0 == __FILE__ 19 puts Base64::DIGITS 20 puts Base64.encode 21 puts Base64.decode 22 end
- Note that we define our methods with a
self.prefix
, which makes them “class methods” of the module.- Outside the
Base64
module, this constant can be referred to asBase64::DIGITS
.- Inside the module, our encode and decode methods can refer to it by its simple name
DIGITS
.- If the two methods had some need to share nonconstant data, they could use a class variable (with a
@@
prefix), just as they could if they were defined in a class.
[~/local/src/ruby/rubytesting/TheRubyProgrammingLanguage/Chapter7ClassesAndModules/modules]$ cat client.rb require 'base64_mod_self' class A def self.tutu Base64::encode end end if $0 == __FILE__ puts A.tutu puts Base64::DIGITS end
[~/local/src/ruby/rubytesting/TheRubyProgrammingLanguage/Chapter7ClassesAndModules/modules]$ ruby -I. client.rb Base64 self.encode hello ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Espacios de Nombres Anidados
- Los módulos y las clases pueden anidarse creando espacios de nombres anidados.
- Una clase o módulo anidado dentro de otro no tiene acceso especial al módulo o clase en la que se anida.
module Base64 DIGITS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' class Encoder def encode end end class Decoder def decode end end # A utility function for use by both classes def Base64.helper end end
- Tenemos dos clases:
Base64::encoder
yBase64::Decoder
. Dentro del módulo las clases pueden referirse la una a la otra y a la constanteDIGITS
por sus nombres simples, sin cualificar.
- Sin embargo, para llamar a
Base64.helper
deben referirse a él por su nombre completo:Base64.helper
.
- Las clases pueden también anidarse. Anidar una clase dentro de otra no le da a la clase ningún privilegio especial de acceso a los métodos y variables en la clase mas externa. Su único efecto es en el espacio de nombres de la clase interna.
- Cuando escribimos una gema es conveniente anidar las clases y módulos - especialmente aquellas clases que no forman parte de la API pública - para no contaminar los espacios de nombres públicos.
Casiano Rodriguez León 2015-01-07