From Fedora Project Wiki

< FWN‎ | Beats

No edit summary
No edit summary
Line 5: Line 5:
LATAM Fedora is a regular column of Spanish language contributions around open source software.  It is our first expansion into incorporating foreign language content into FWN.   
LATAM Fedora is a regular column of Spanish language contributions around open source software.  It is our first expansion into incorporating foreign language content into FWN.   


This week's contribution is from [[User:gomix|Guillermo Gómez]], a primer on Ruby Ping.  Enjoy!
This week's contribution is from [[User:gomix|Guillermo Gómez]], a second installment primer on Ruby.  Enjoy!


=== SOX ===
===Ruby Capítulo 2 : Una clase algo más completa===
SoX<ref>
http://sox.sourceforge.net/</ref>, la navaja suiza para la manipulación de audio.


==== Agregando Soporte mp3 y m4a ====
Siguiendo nuestra secuencia al estilo tutorial, en esta edición vamos a completar un poco más nuestras clases, introduciresmo los conceptos de métodos y variables de clase.


Fedora no incluye soporte para MP3 en sus paquetes multimedia, debido a problemas de patentes sobre el algoritmo que permite comprimir y descromprimir mp3. De forma similar ocurre con el formato m4a. Sin embargo usted puede vivir en ciertos países donde no apliquen las limitaciones de la legislación de los EEUU, entonces si es así, veamos cómo podemos agregar el soporte deseado para mp3 y m4a entre otros formatos a sox.
Una variable de clase es una variable compartida de la clase misma. Sólo existe una copia de una variable de clase en particular para una clase dada. Los nombres de las variables de clase comienzan con @@ tal como en @@reproducciones.


==== Agregar soporte recompilando el Source RPM (SRPM) ====
<code>
1 class Cancion
2  @@reproducciones = 0
3
4  def Cancion.reproducciones
5    @@reproducciones
6  end
7
8  def reproducir
9    @@reproducciones =+ 1
10  end
11 end
</code>
 
A diferencia de las variables de instancia y variables globales, las variables de clase deben se inicializadas antes de poder ser utilizadas, usualmente se hace con una declaración simple en el cuerpo de la definición de la clase. En el código anterior igualmente se ha introducido el concepto de método de clase. Un método de clase es un método que no necesita que se instancie la clase para ser invocado, es decir, "son métodos propios de la clase y no de sus objetos".


===== Requisitos =====
Su utilidad es obvia en el ejemplo, se quiere saber cuántas reproducciones se han hecho en total en nuestro reproductor de música. Esta información no es específica a una canción en particular, es decir, no es sujeto de las instancias sino de la clase misma. La diferencia al momento de declarar el método de clase es que debe anteponer el nombre de la clase al método, tiene dos opciones, o usar explícitamente Cancion, o self. El uso de *self" da mayor flexibilidad ya que permite cambiar el nombre de la clase sin mayores traumas.


     * Herramientas para compilación
<code>
     * rpmbuild
1 class Cancion
    * yum-buildep
2  @@reproducciones = 0
    * De RPM Fusion, lame, lame-libs, lame-devel, libmad, libmad-devel, ffmpeg y ffmpeg-devel
3
4  def self.reproducciones
5     @@reproducciones
6  end
7
8  def reproducir
9     @@reproducciones =+ 1
10  end
11 end
</code>


El procedimiento de instalación de software es, como root:
====Constantes vs variables====


''Herramientas para compilar''
Las variables y constantes en Ruby mantienen referencias a objetos. Las variables no poseen un tipo intrínseco, a cambio el tipo es únicamente definido por los mensajes a los que responde el objeto referenciado.


<code>  
Una constante en Ruby también es una referencia a un objeto. Las constantes son creadas cuando son asignadas por primera vez, a diferencia de otros lenguajes Ruby le permite alterar el valor de las constantes si bien ello provocará un mensaje de alerta. En general usted no debe alterar una constante en tiempo de ejecución y debería evitarlo a toda costa.
  $ yum -y groupinstall "Development Tools"
 
  $ yum -y install rpmdevtools
<code>
  1 >> MI_CONSTANTE = 1
2 => 1
3 >> MI_CONSTANTE = 2
4 (irb):23: warning: already initialized constant MI_CONSTANTE
  5 => 2
</code>
</code>


''Dependencias para poder compilar sox según Fedora''
Note como las constantes pueden declararse dentro de la definición de clase lo que nos lleva a la definición de constante de clase y a la noción de espacios de nombres por la forma en que nos referimos a dichas constantes.


<code>
<code>
  $ yum-builddep -y sox
  1 class Cancion
2  VERSION="1.0"
3 end
</code>
</code>
''Librerías adicionales para la compilación (soporte mp3)''


<code>
<code>
  $ yum -y install lame lame-libs lame-devel
  1 >> Cancion::VERSION
  $ yum -y install libmad libmad-devel
  2 => "1.0"
  $ yum -y install ffmpeg ffmpeg-devel
  3 >> VERSION
4 => "1.8.7"
</code>
</code>


==== Construcción e Instalación del RPM ====
Note que VERSION no referencia ni colisiona con Cancion::VERSION.


Ahora para reconstruir SoX con soporte mp3 el procedimiento como usuario regular es:
====El poder de herencia====
 
Tal vez el santo grial de la programación es el principio DRY, "Don Repeat Yourself". Una forma de evitar repetirse, es escribir código reusable, cada vez que estamos escribiendo nuevo código y tenemos esa sensación de deja-vu de que ya esto lo hicimos una vez en el pasado, es porque no estamos reusando nuestro código de forma inteligente. En POO la herencia es una excelente forma de mantener el código reusable sin mayores repeticiones.
 
La herencia le permite crear clases que sean refinamientos o especializaciones de otra clase. Por ejemplo, y siguiendo el ejemplo de Cancion en nuestro reproductor de música ahora a alguien se le ocurrió que sería interesante que se incluyera el soporte para canciones de tipo Karaoke. La única diferencia con las otras canciones es que las canciones Karaoke tienen asociadas la letra de la canción en conjunto con infomación de sincronización para reproducir las letras del Karaoke en nuestro flamante reproductor ahora con una gran pantalla de video.


<code>
<code>
  $ cd
  1 class Karaoke < Cancion
  $ rpmdev-setuptree (si no lo ha hecho antes)
  2  def initialize(nombre, artista, duracion, letra)
$ yumdownloader --source sox (descarga los fuentes srpm)
  3     super(nombre, artista, duracion)
  $ rpmbuild --rebuild sox-14.3.0-1.fc13.src.rpm (compila/construye rpm)
  4    @letra = letra
  $ cd rpmbuild/RPMS/x86_64
  5   end
  $ su
  6 end
*contraseña*
# rpm -vhi --force sox-14.3.0-1.fc13.x86_64.rpm
Preparando...            ########################################### [100%]
1:sox                    ########################################### [100%]
...
# sox -h
...
AUDIO FILE FORMATS: 8svx aif aifc aiff aiffc al amb au avi avr caf cdda cdr cvs cvsd cvu dat dvms f32 f4 f64 f8 fap ffmpeg   flac fssd gsm hcom htk ima ircam la lpc lpc10 lu m4a mat mat4 mat5 maud mp2 mp3 mp4 mpg nist ogg paf prc pvf raw s1 s16 s2 s24 s3 s32 s4 s8 sb sd2 sds sf sl smp snd sndfile sndr sndt sou sox sph sw txw u1 u16 u2 u24 u3 u32 u4 u8 ub ul uw vms voc vorbis  vox w64 wav wavpcm wmv wv wve xa xi
PLAYLIST FORMATS: m3u pls
  ...
</code>
</code>


NOTA: Procedimiento probado en F8, F9, F10, F11, F12 y F13, en el tiempo las versiones pueden cambiar, en el ejemplo se muestra la versión más reciente. Para versiones anteriores a F13, el compilado es para i586, a partir de F12 es i686. En el caso de x86_64, el compilado está en el directorio rpmbuild/RPMS/x86_64 .
El "< Cancion" en la definición de la clase le indica a Ruby que Karaoke es un subclase de Cancion, o en dirección opuesta, Cancion es la superclase de Karaoke. De esta forma la clase hija hereda todos los métodos y declaraciones de variables de su padre. Al invocar un método sobre un objeto o clase, Ruby defiere su ubicación hasta el momento de ejecución, en dicho momento Ruby primero mira en la clase para determinar si existe el método invocado, si no es así, intenta en el padre, y así atravesando todos los ancestros de la clase hasta ubicar el método invocado. Si se acaban los ancestros donde buscar, Ruby ejecuta una acción especial que puede ser interceptada si se desea Object#method_missing, si no, produce un error.


Note la inclusión de mp3 y m4a en los formatos soportados. Ahora puede reproducir su mp3 o m4a desde la consola. Sox también permite convertir entre formatos y tiene muchas otras aplicaciones. Abajo reproduzco un mp3 de AC/DC.
Cada clase especializada maneja sus detalles, para el resto se utiliza super, es decir, el método del padre o de su ancestro. De esta forma, por ejemplo, en nuestra definición de Karaoke#initialize dejamos que la inicialización de todo lo común a Cancion ocurra igual que antes por medio de la llamada a super con los respectivos parámetros necesarios, luego inicializamos los datos específicos a nuetras clase Karaoke.


=== Convertir mp3 ===
====Espacios de nombres====


Otra aplicación común de sox es convertir de un formato a otro, por ejemplo de mp3 a cdr o wav, con cdr se está listo para quemar un CD Audio :)
En la medida que escriba programas Ruby cada vez más grandes, usted naturalmente se encontrará con código reusable, librerías de rutinas relacionadas entre sí por ejemplo. Usted deseará separar dicho código en distintos archivos separados de tal forma que el contenido pueda ser reusado entre diferentes programas Ruby. Frecuentemente este código será organizado en clases.
 
Otras veces ello simplemente no es conveniente o no aplica, son un grupo de métodos que desea reusar, usted puede simplemente colocarlos en un archivo y cargar dicho archivo en su programa con load o require. Esto funciona pero tiene un problema, digamos que se crea una librería para cocinar con los métodos calentar , mezclar, amasar en un archivo cocina.rb y otra librería para atletas con los métodos calentar, correr, descansar en el archivo atleta.rb. Si carga ambos archivos uno después del otro, simplemente el método calentar colisiona y sólo el más recientemente cargado tendrá la definicón actual del método, el otro simplemente será olvidado, en resumen la colisión en los nombres es el problema.
 
La respuesta es el mecanismo de modulos. Los modulos definen un espacio de nombres en donde sus métodos y constantes pueden aplicar sin tener que preocuparse en colisionar con otros métodos y constantes:


<code>
<code>
  $ sox -V Boinga.mp3 Boinga.cdr
  1 module Cocina
  sox: Detected file format type: mp3
  2  ESCUELA="Latinoamericana"
  3  def Cocina.calentar(x)
  4    # Se espera que x sea un valor númerico para representar temperatura en ºC
  5    # ..
  6  end
  7 ...
  8 end
  9
10 module Atleta
  11  ESCUELA="Simón Bolívar"
12  def Atleta.calentar(t)
13    # Se espera que t sea un valor numérico que represente tiempo en segundos
14    # ..
  15  end
16 end
</code>


  sox: Input file Boinga.mp3: using sample rate 44100
<code>
  size shorts, encoding MPEG audio (layer I, II or III), 2 channels
  1 >> Cocina::ESCUELA
  sox: Output file Boinga.cdr: using sample rate 44100
  2 => "Latinoamericana"
  size shorts, encoding signed (2's complement), 2 channels
  3 >> Atleta::ESCUELA
  sox: Output file: comment "Processed by SoX"
4 => "Simon Bolivar"
5 >> include Atleta
6 => Object
7 >> Atleta.calentar(1000)
8 calentando 1000 segundos
9 => nil
10 >> include Cocina
11 => Object
  12 >> Cocina.calentar(10)
  13 => 10
</code>
</code>


Convirtamos ahora a un formato libre, ogg.
Ahora entonces tiene mucho menos probabilidades de provocar colisiones, note que debe cargar el código, y luego include para usar las funcionalidades del módulo.
Herencia múltiples vs Mixins¶
 
Algunos lenguajes orientados a objetos, tales como C++, soportan herencia múltiple en donde una clase puede tener más de una superclase heredando funcionalidad de cada una de ellas. Si bien potente, esta técnica puede ser peligrosa ya que la jerarquía puede tener ambigüedades. Otros lenguajes como java y C# soportan sólo herencia simple. Si bien más limpia y simple, la herencia simple también tiene sus desventajas, en la realidad los objetos heredan atributos de múltiples fuentes en el mundo real.
 
Ruby ofrece una alternativa interesante y poderosa que le ofrece la simplicidad de la herencia simple y el poder la herencia múltiple. Una clase Ruby tiene una única clase padre, en consecuencia Ruby es un lenguaje con herencia simple, sin embargo, las clases Ruby pueden incluir la funcionalidad de cualquier cantidad de mixins (un mixin es una especie de definición parcial de clase). Nuevamente dejemos que Ruby hable, creemos nuestro archivo con la definición de módulo y un par de clases tontas que lo usen como mixin:
 
=====mixin_module.rb=====


<code>
<code>
$ sox -V Boinga.mp3 Boinga.ogg
  1 module Debug
  sox: Detected file format type: mp3
  2  def quien_soy?
 
  3    "#{self.class.name} (\##{self.objet_id}): #{self.to_s}"
  sox: Input file Boinga.mp3: using sample rate 44100
  4  end
  size shorts, encoding MPEG audio (layer I, II or III), 2 channels
  5 end
  sox: Output file Boinga.ogg: using sample rate 44100
  6
  size shorts, encoding Vorbis, 2 channels
  7 class Cocina
  sox: Output file: comment "Processed by SoX"  
  8  include Debug
  9  def estilo
10    puts "Italiana"
  11  end
12 end
  13
  14 class Nevera
  15  include Debug
  16  def capacidad
  17    puts "150 pies cúbicos"  
18  end
19 end
</code>
</code>


Veamos los tamaños resultantes solo por curiosidad incluyendo otros formatos sin ningún parámetro adicional al convertir, es decir, usando los valores por omisión.
Si ahora cargamos dichas definiciones de módulo y clases en irb, podemos evidenciar y experimentar con el uso de los mixins (note que le voy a pasar la forma de hacerlo):


<code>
<code>
  $ ls -lh Boinga*
  1 $ irb
  -rw-rw-r-- 1 gomix gomix  23M Sep 22 14:50 Boinga.au
  2 >> load 'mixin_module.rb'
  -rw-rw-r-- 1 gomix gomix 23M Sep 22 14:51 Boinga.avr
  3 => true
  -rw-rw-r-- 1 gomix gomix 23M Sep 22 14:24 Boinga.cdr
  4 >> nevera = Nevera.new
  -rw-rw-r-- 1 gomix gomix 2.6M Nov 11 2006 Boinga.mp3
  5 => #<Nevera:0xb7587b38>
  -rw-rw-r-- 1 gomix gomix 1.5M Sep 22 14:26 Boinga.ogg
  6 >> cocina = Cocina.new
  -rw-rw-r-- 1 gomix gomix  23M Sep 22 14:35 Boinga.wav
  7 => #<Cocina:0xb7585c5c>
  8 >> nevera.quien_soy?
  9 => "Nevera (#-609469028): #<Nevera:0xb7587b38>"
10 >> cocina.quien_soy?
  11 => "Cocina (#-609472978): #<Cocina:0xb7585c5c>"
</code>


AplicacionesDeUsuario_Audio_Sox_mp3_sox-play-mp3.png (25.2 kB)
Bien, es todo por hoy, nos recontraremos en un tercer capítulo dedicado a métodos en una próxima edición de esta serie dedicada a aprender Ruby.
</code>
 
Este artículo se mantiene en línea en gomix.fedora-ve.org para posibles mejoras y erratas.


Guillermo Gómez
Guillermo Gómez

Revision as of 20:27, 30 March 2011

LATAM Fedora!

LATAM Fedora is a regular column of Spanish language contributions around open source software. It is our first expansion into incorporating foreign language content into FWN.

This week's contribution is from Guillermo Gómez, a second installment primer on Ruby. Enjoy!

Ruby Capítulo 2 : Una clase algo más completa

Siguiendo nuestra secuencia al estilo tutorial, en esta edición vamos a completar un poco más nuestras clases, introduciresmo los conceptos de métodos y variables de clase.

Una variable de clase es una variable compartida de la clase misma. Sólo existe una copia de una variable de clase en particular para una clase dada. Los nombres de las variables de clase comienzan con @@ tal como en @@reproducciones.

1 class Cancion
2   @@reproducciones = 0
3 
4   def Cancion.reproducciones
5     @@reproducciones
6   end
7 
8   def reproducir
9     @@reproducciones =+ 1
10   end
11 end

A diferencia de las variables de instancia y variables globales, las variables de clase deben se inicializadas antes de poder ser utilizadas, usualmente se hace con una declaración simple en el cuerpo de la definición de la clase. En el código anterior igualmente se ha introducido el concepto de método de clase. Un método de clase es un método que no necesita que se instancie la clase para ser invocado, es decir, "son métodos propios de la clase y no de sus objetos".

Su utilidad es obvia en el ejemplo, se quiere saber cuántas reproducciones se han hecho en total en nuestro reproductor de música. Esta información no es específica a una canción en particular, es decir, no es sujeto de las instancias sino de la clase misma. La diferencia al momento de declarar el método de clase es que debe anteponer el nombre de la clase al método, tiene dos opciones, o usar explícitamente Cancion, o self. El uso de *self" da mayor flexibilidad ya que permite cambiar el nombre de la clase sin mayores traumas.

1 class Cancion
2   @@reproducciones = 0
3 
4   def self.reproducciones
5     @@reproducciones
6   end
7 
8   def reproducir
9     @@reproducciones =+ 1
10   end
11 end

Constantes vs variables

Las variables y constantes en Ruby mantienen referencias a objetos. Las variables no poseen un tipo intrínseco, a cambio el tipo es únicamente definido por los mensajes a los que responde el objeto referenciado.

Una constante en Ruby también es una referencia a un objeto. Las constantes son creadas cuando son asignadas por primera vez, a diferencia de otros lenguajes Ruby le permite alterar el valor de las constantes si bien ello provocará un mensaje de alerta. En general usted no debe alterar una constante en tiempo de ejecución y debería evitarlo a toda costa.

1 >> MI_CONSTANTE = 1
2 => 1
3 >> MI_CONSTANTE = 2
4 (irb):23: warning: already initialized constant MI_CONSTANTE
5 => 2

Note como las constantes pueden declararse dentro de la definición de clase lo que nos lleva a la definición de constante de clase y a la noción de espacios de nombres por la forma en que nos referimos a dichas constantes.

1 class Cancion 
2   VERSION="1.0" 
3 end

1 >> Cancion::VERSION
2 => "1.0" 
3 >> VERSION
4 => "1.8.7" 

Note que VERSION no referencia ni colisiona con Cancion::VERSION.

El poder de herencia

Tal vez el santo grial de la programación es el principio DRY, "Don Repeat Yourself". Una forma de evitar repetirse, es escribir código reusable, cada vez que estamos escribiendo nuevo código y tenemos esa sensación de deja-vu de que ya esto lo hicimos una vez en el pasado, es porque no estamos reusando nuestro código de forma inteligente. En POO la herencia es una excelente forma de mantener el código reusable sin mayores repeticiones.

La herencia le permite crear clases que sean refinamientos o especializaciones de otra clase. Por ejemplo, y siguiendo el ejemplo de Cancion en nuestro reproductor de música ahora a alguien se le ocurrió que sería interesante que se incluyera el soporte para canciones de tipo Karaoke. La única diferencia con las otras canciones es que las canciones Karaoke tienen asociadas la letra de la canción en conjunto con infomación de sincronización para reproducir las letras del Karaoke en nuestro flamante reproductor ahora con una gran pantalla de video.

1 class Karaoke < Cancion
2   def initialize(nombre, artista, duracion, letra)
3     super(nombre, artista, duracion)
4     @letra = letra
5   end
6 end

El "< Cancion" en la definición de la clase le indica a Ruby que Karaoke es un subclase de Cancion, o en dirección opuesta, Cancion es la superclase de Karaoke. De esta forma la clase hija hereda todos los métodos y declaraciones de variables de su padre. Al invocar un método sobre un objeto o clase, Ruby defiere su ubicación hasta el momento de ejecución, en dicho momento Ruby primero mira en la clase para determinar si existe el método invocado, si no es así, intenta en el padre, y así atravesando todos los ancestros de la clase hasta ubicar el método invocado. Si se acaban los ancestros donde buscar, Ruby ejecuta una acción especial que puede ser interceptada si se desea Object#method_missing, si no, produce un error.

Cada clase especializada maneja sus detalles, para el resto se utiliza super, es decir, el método del padre o de su ancestro. De esta forma, por ejemplo, en nuestra definición de Karaoke#initialize dejamos que la inicialización de todo lo común a Cancion ocurra igual que antes por medio de la llamada a super con los respectivos parámetros necesarios, luego inicializamos los datos específicos a nuetras clase Karaoke.

Espacios de nombres

En la medida que escriba programas Ruby cada vez más grandes, usted naturalmente se encontrará con código reusable, librerías de rutinas relacionadas entre sí por ejemplo. Usted deseará separar dicho código en distintos archivos separados de tal forma que el contenido pueda ser reusado entre diferentes programas Ruby. Frecuentemente este código será organizado en clases.

Otras veces ello simplemente no es conveniente o no aplica, son un grupo de métodos que desea reusar, usted puede simplemente colocarlos en un archivo y cargar dicho archivo en su programa con load o require. Esto funciona pero tiene un problema, digamos que se crea una librería para cocinar con los métodos calentar , mezclar, amasar en un archivo cocina.rb y otra librería para atletas con los métodos calentar, correr, descansar en el archivo atleta.rb. Si carga ambos archivos uno después del otro, simplemente el método calentar colisiona y sólo el más recientemente cargado tendrá la definicón actual del método, el otro simplemente será olvidado, en resumen la colisión en los nombres es el problema.

La respuesta es el mecanismo de modulos. Los modulos definen un espacio de nombres en donde sus métodos y constantes pueden aplicar sin tener que preocuparse en colisionar con otros métodos y constantes:

 1 module Cocina
 2   ESCUELA="Latinoamericana" 
 3   def Cocina.calentar(x)
 4    # Se espera que x sea un valor númerico para representar temperatura en ºC
 5    # ..
 6   end
 7 ...
 8 end
 9 
10 module Atleta
11   ESCUELA="Simón Bolívar" 
12   def Atleta.calentar(t)
13     # Se espera que t sea un valor numérico que represente tiempo en segundos
14     # ..
15   end
16 end

1 >> Cocina::ESCUELA
2 => "Latinoamericana" 
3 >> Atleta::ESCUELA
4 => "Simon Bolivar" 
5 >> include Atleta
6 => Object
7 >> Atleta.calentar(1000)
8 calentando 1000 segundos
9 => nil
10 >> include Cocina
11 => Object
12 >> Cocina.calentar(10)
13 => 10

Ahora entonces tiene mucho menos probabilidades de provocar colisiones, note que debe cargar el código, y luego include para usar las funcionalidades del módulo. Herencia múltiples vs Mixins¶

Algunos lenguajes orientados a objetos, tales como C++, soportan herencia múltiple en donde una clase puede tener más de una superclase heredando funcionalidad de cada una de ellas. Si bien potente, esta técnica puede ser peligrosa ya que la jerarquía puede tener ambigüedades. Otros lenguajes como java y C# soportan sólo herencia simple. Si bien más limpia y simple, la herencia simple también tiene sus desventajas, en la realidad los objetos heredan atributos de múltiples fuentes en el mundo real.

Ruby ofrece una alternativa interesante y poderosa que le ofrece la simplicidad de la herencia simple y el poder la herencia múltiple. Una clase Ruby tiene una única clase padre, en consecuencia Ruby es un lenguaje con herencia simple, sin embargo, las clases Ruby pueden incluir la funcionalidad de cualquier cantidad de mixins (un mixin es una especie de definición parcial de clase). Nuevamente dejemos que Ruby hable, creemos nuestro archivo con la definición de módulo y un par de clases tontas que lo usen como mixin:

mixin_module.rb

 1 module Debug
 2   def quien_soy?
 3     "#{self.class.name} (\##{self.objet_id}): #{self.to_s}" 
 4   end
 5 end
 6 
 7 class Cocina
 8   include Debug
 9   def estilo
10     puts "Italiana" 
11   end
12 end
13 
14 class Nevera
15   include Debug
16   def capacidad
17     puts "150 pies cúbicos" 
18   end
19 end

Si ahora cargamos dichas definiciones de módulo y clases en irb, podemos evidenciar y experimentar con el uso de los mixins (note que le voy a pasar la forma de hacerlo):

1 $ irb 
2 >> load 'mixin_module.rb'
3 => true
4 >> nevera = Nevera.new
5 => #<Nevera:0xb7587b38>
6 >> cocina = Cocina.new
7 => #<Cocina:0xb7585c5c>
8 >> nevera.quien_soy?
9 => "Nevera (#-609469028): #<Nevera:0xb7587b38>" 
10 >> cocina.quien_soy?
11 => "Cocina (#-609472978): #<Cocina:0xb7585c5c>" 

Bien, es todo por hoy, nos recontraremos en un tercer capítulo dedicado a métodos en una próxima edición de esta serie dedicada a aprender Ruby.

Este artículo se mantiene en línea en gomix.fedora-ve.org para posibles mejoras y erratas.

Guillermo Gómez