Ahora vamos a crear y usar un objeto anfitrión:

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):035:0&gt;</span><span class="w"> </span><span class="n">a</span> <span class="o">=</span> <span class="no">Anfitrion</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"Juan"</span><span class="p">)</span>
<span class="gp">=&gt; #&lt;Anfitrion:0x16cac @nombre="Juan"&gt;</span><span class="w">
</span><span class="gp">irb(main):036:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">decir_hola</span>
<span class="go">Hola Juan
</span><span class="p">=&gt;</span> <span class="kp">nil</span>
<span class="gp">irb(main):037:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">decir_adios</span>
<span class="go">Adiós Juan, vuelve pronto.
</span><span class="p">=&gt;</span> <span class="kp">nil</span></code></pre></figure>

Una vez que el objeto `a` es creado, nos recuerda que el nombre es Juan.
Mmm, ¿y si queremos acceder al nombre directamente?

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):038:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="o">.</span><span class="vi">@nombre</span>
<span class="gr">SyntaxError: compile error
(irb):52: syntax error
        from (irb):52</span></code></pre></figure>

No, no podemos.

## Por debajo de la piel del objeto

Las variables de instancia se esconden dentro del objeto. No están tan
escondidas, las puedes ver cuando inspeccionas el objeto, y hay otras
formas de acceder a ellas, pero Ruby es fiel a las buenas costumbres de
la programación orientada a objetos manteniendo los datos lo más
privados posible.

Entonces, ¿qué métodos están disponibles para los objetos Anfitrion?

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):039:0&gt;</span><span class="w"> </span><span class="no">Anfitrion</span><span class="p">.</span><span class="nf">instance_methods</span>
<span class="p">=&gt;</span> <span class="p">[</span><span class="s2">"method"</span><span class="p">,</span> <span class="s2">"send"</span><span class="p">,</span> <span class="s2">"object_id"</span><span class="p">,</span> <span class="s2">"singleton_methods"</span><span class="p">,</span>
    <span class="s2">"__send__"</span><span class="p">,</span> <span class="s2">"equal?"</span><span class="p">,</span> <span class="s2">"taint"</span><span class="p">,</span> <span class="s2">"frozen?"</span><span class="p">,</span>
    <span class="s2">"instance_variable_get"</span><span class="p">,</span> <span class="s2">"kind_of?"</span><span class="p">,</span> <span class="s2">"to_a"</span><span class="p">,</span>
    <span class="s2">"instance_eval"</span><span class="p">,</span> <span class="s2">"type"</span><span class="p">,</span> <span class="s2">"protected_methods"</span><span class="p">,</span> <span class="s2">"extend"</span><span class="p">,</span>
    <span class="s2">"eql?"</span><span class="p">,</span> <span class="s2">"display"</span><span class="p">,</span> <span class="s2">"instance_variable_set"</span><span class="p">,</span> <span class="s2">"hash"</span><span class="p">,</span>
    <span class="s2">"is_a?"</span><span class="p">,</span> <span class="s2">"to_s"</span><span class="p">,</span> <span class="s2">"class"</span><span class="p">,</span> <span class="s2">"tainted?"</span><span class="p">,</span> <span class="s2">"private_methods"</span><span class="p">,</span>
    <span class="s2">"untaint"</span><span class="p">,</span> <span class="s2">"decir_hola"</span><span class="p">,</span> <span class="s2">"id"</span><span class="p">,</span> <span class="s2">"inspect"</span><span class="p">,</span> <span class="s2">"=="</span><span class="p">,</span> <span class="s2">"==="</span><span class="p">,</span>
    <span class="s2">"clone"</span><span class="p">,</span> <span class="s2">"public_methods"</span><span class="p">,</span> <span class="s2">"respond_to?"</span><span class="p">,</span> <span class="s2">"freeze"</span><span class="p">,</span>
    <span class="s2">"decir_adios"</span><span class="p">,</span> <span class="s2">"__id__"</span><span class="p">,</span> <span class="s2">"=~"</span><span class="p">,</span> <span class="s2">"methods"</span><span class="p">,</span> <span class="s2">"nil?"</span><span class="p">,</span> <span class="s2">"dup"</span><span class="p">,</span>
    <span class="s2">"instance_variables"</span><span class="p">,</span> <span class="s2">"instance_of?"</span><span class="p">]</span></code></pre></figure>

Bien. Eso es un montón de métodos. Nosotros sólo definimos dos métodos.
¿Qué es lo que está sucediendo? Bueno, estos son **todos** los métodos
para los objetos Anfitrion, una lista completa, incluyendo los que están
definidos en las superclases de Anfitrion. Si queremos listar únicamente
los métodos definidos para la clase Anfitrion podemos pedirle que no
incluya sus ancestros pasándole el parámetro `false`, que significa que
no queremos los métodos definidos por sus ancestros.

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):040:0&gt;</span><span class="w"> </span><span class="no">Anfitrion</span><span class="p">.</span><span class="nf">instance_methods</span><span class="p">(</span><span class="kp">false</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="p">[</span><span class="s2">"decir_adios"</span><span class="p">,</span> <span class="s2">"decir_hola"</span><span class="p">]</span></code></pre></figure>

Ah, hay más cosas como esa. Veamos a qué métodos puede responder nuestro
objeto anfitrión:

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):041:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"nombre"</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">false</span>
<span class="gp">irb(main):042:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"decir_hola"</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">true</span>
<span class="gp">irb(main):043:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"to_s"</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">true</span></code></pre></figure>

Así que, sabe `decir_hola`, y `to_s` (que significa “convertir algo en
un string”, un método que está definido por defecto para todos los
objetos), pero no reconoce `nombre` como un método.

## Modificando clases—Nunca es demasiado tarde

¿Pero qué pasa si quieres poder ver o modificar el nombre? Ruby provee
una forma fácil para permitir acceder a las variables de un objeto.

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):044:0&gt;</span><span class="w"> </span><span class="k">class</span> <span class="nc">Anfitrion</span>
<span class="gp">irb(main):045:1&gt;</span><span class="w">   </span><span class="nb">attr_accessor</span> <span class="ss">:nombre</span>
<span class="gp">irb(main):046:1&gt;</span><span class="w"> </span><span class="k">end</span>
<span class="p">=&gt;</span> <span class="p">[</span><span class="ss">:nombre</span><span class="p">,</span> <span class="ss">:nombre</span><span class="o">=</span><span class="p">]</span></code></pre></figure>

En Ruby, puedes volver a abrir una clase y modificarla. Eso no cambia
objetos que ya existan, pero afecta a los nuevos objetos que puedas
crear. Así que vamos a crear un nuevo objeto y juguemos con su propiedad
`@nombre`.

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):047:0&gt;</span><span class="w"> </span><span class="n">a</span> <span class="o">=</span> <span class="no">Anfitrion</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"Pedro"</span><span class="p">)</span>
<span class="gp">=&gt; #&lt;Anfitrion:0x3c9b0 @nombre="Pedro"&gt;</span><span class="w">
</span><span class="gp">irb(main):048:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"nombre"</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">true</span>
<span class="gp">irb(main):049:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"nombre="</span><span class="p">)</span>
<span class="p">=&gt;</span> <span class="kp">true</span>
<span class="gp">irb(main):050:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">decir_hola</span>
<span class="go">Hola Pedro
</span><span class="p">=&gt;</span> <span class="kp">nil</span>
<span class="gp">irb(main):051:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">nombre</span><span class="o">=</span><span class="s2">"Matilde"</span>
<span class="p">=&gt;</span> <span class="s2">"Matilde"</span>
<span class="gp">irb(main):052:0&gt;</span><span class="w"> </span><span class="n">a</span>
<span class="gp">=&gt; #&lt;Anfitrion:0x3c9b0 @nombre="Matilde"&gt;</span><span class="w">
</span><span class="gp">irb(main):053:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">nombre</span>
<span class="p">=&gt;</span> <span class="s2">"Matilde"</span>
<span class="gp">irb(main):054:0&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="nf">decir_hola</span>
<span class="go">Hola Matilde
</span><span class="p">=&gt;</span> <span class="kp">nil</span></code></pre></figure>

El uso de `attr_accessor` determinó que se definan dos nuevos métodos
por nosotros, `nombre` para obtener el valor, y `nombre=` para
modificarlo.

## Saludando a todo el mundo, ¡MegaAnfitrion no niega el saludo a nadie!

De todas formas, este anfitrión no es tan interesante, sólo puede
trabajar con una persona a la vez. ¿Qué pasaría si tuviéramos alguna
clase MegaAnfitrion que pudiera saludar al mundo, a una persona, o una
lista completa de personas?

Escribamos esto en un archivo en vez de usar directamente el intérprete
interactivo de Ruby IRB.

Para salir de IRB, escribe “quit”, “exit” o simplemente presiona
Control-D.

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1">#!/usr/bin/env ruby</span>

<span class="k">class</span> <span class="nc">MegaAnfitrion</span>
  <span class="nb">attr_accessor</span> <span class="ss">:nombres</span>

  <span class="c1"># Crear el objeto</span>
  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">nombres</span> <span class="o">=</span> <span class="s2">"Mundo"</span><span class="p">)</span>
    <span class="vi">@nombres</span> <span class="o">=</span> <span class="n">nombres</span>
  <span class="k">end</span>

  <span class="c1"># Decirle hola a todos</span>
  <span class="k">def</span> <span class="nf">decir_hola</span>
    <span class="k">if</span> <span class="vi">@nombres</span><span class="p">.</span><span class="nf">nil?</span>
      <span class="nb">puts</span> <span class="s2">"..."</span>
    <span class="k">elsif</span> <span class="vi">@nombres</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"each"</span><span class="p">)</span>
      <span class="c1"># @nombres es una lista de algún tipo,</span>
      <span class="c1"># ¡así que podemos iterar!</span>
      <span class="vi">@nombres</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">nombre</span><span class="o">|</span>
        <span class="nb">puts</span> <span class="s2">"Hola </span><span class="si">#{</span><span class="n">nombre</span><span class="si">}</span><span class="s2">"</span>
      <span class="k">end</span>
    <span class="k">else</span>
      <span class="nb">puts</span> <span class="s2">"Hola </span><span class="si">#{</span><span class="vi">@nombres</span><span class="si">}</span><span class="s2">"</span>
    <span class="k">end</span>
  <span class="k">end</span>

  <span class="c1"># Decirle adiós a todos</span>
  <span class="k">def</span> <span class="nf">decir_adios</span>
    <span class="k">if</span> <span class="vi">@nombres</span><span class="p">.</span><span class="nf">nil?</span>
      <span class="nb">puts</span> <span class="s2">"..."</span>
    <span class="k">elsif</span> <span class="vi">@nombres</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"join"</span><span class="p">)</span>
      <span class="c1"># Juntar los elementos de la lista</span>
      <span class="c1"># usando la coma como separador</span>
      <span class="nb">puts</span> <span class="s2">"Adiós </span><span class="si">#{</span><span class="vi">@nombres</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">", "</span><span class="p">)</span><span class="si">}</span><span class="s2">. Vuelvan pronto."</span>
    <span class="k">else</span>
      <span class="nb">puts</span> <span class="s2">"Adiós </span><span class="si">#{</span><span class="vi">@nombres</span><span class="si">}</span><span class="s2">. Vuelve pronto."</span>
    <span class="k">end</span>
  <span class="k">end</span>

<span class="k">end</span>


<span class="k">if</span> <span class="kp">__FILE__</span> <span class="o">==</span> <span class="vg">$0</span>
  <span class="n">ma</span> <span class="o">=</span> <span class="no">MegaAnfitrion</span><span class="p">.</span><span class="nf">new</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">decir_hola</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">decir_adios</span>

  <span class="c1"># Cambiar el nombre a "Diego"</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">nombres</span> <span class="o">=</span> <span class="s2">"Diego"</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">decir_hola</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">decir_adios</span>

  <span class="c1"># Cambiar el nombre a un vector de nombres</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">nombres</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Alberto"</span><span class="p">,</span> <span class="s2">"Beatriz"</span><span class="p">,</span> <span class="s2">"Carlos"</span><span class="p">,</span>
    <span class="s2">"David"</span><span class="p">,</span> <span class="s2">"Ernesto"</span><span class="p">]</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">decir_hola</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">decir_adios</span>

  <span class="c1"># Cambiarlo a nil</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">nombres</span> <span class="o">=</span> <span class="kp">nil</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">decir_hola</span>
  <span class="n">ma</span><span class="p">.</span><span class="nf">decir_adios</span>
<span class="k">end</span></code></pre></figure>

Guarda este archivo como “ri20min.rb”, y ejecútalo con “ruby
ri20min.rb”. El resultado debería ser:

    Hola Mundo
    Adiós Mundo. Vuelve pronto.
    Hola Diego
    Adiós Diego. Vuelve pronto.
    Hola Alberto
    Hola Beatriz
    Hola Carlos
    Hola David
    Hola Ernesto
    Adiós Alberto, Beatriz, Carlos, David, Ernesto. Vuelvan pronto.
    ...
    ...
{: .code}

Hay un montón de cosas nuevas en este nuevo ejemplo en las que podemos
[echar una mirada más profunda](../4/).
