Erzeugen wir nun ein Greeter-Objekt und benutzen es:

<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">g</span> <span class="o">=</span> <span class="no">Greeter</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"Patrick"</span><span class="p">)</span>
<span class="gp">=&gt; #&lt;Greeter:0x16cac @name="Patrick"&gt;</span><span class="w">
</span><span class="gp">irb(main):036:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">sag_hallo</span>
<span class="go">Hallo, Patrick!
</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">g</span><span class="p">.</span><span class="nf">sag_tschuess</span>
<span class="go">Tschuess, Patrick, bis bald!
</span><span class="p">=&gt;</span> <span class="kp">nil</span></code></pre></figure>

Wenn `g` einmal erzeugt wurde, merkt es sich, dass der Name Patrick ist.
Hmm, und wenn wir direkt auf den Namen im Objekt zugreifen wollen?

<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">g</span><span class="o">.</span><span class="vi">@name</span>
<span class="go">&lt;internal:kernel&gt;:187:in `loop': (irb):52: syntax error, unexpected instance variable (SyntaxError)</span></code></pre></figure>

Nö, das geht offensichtlich nicht.

## Objekten unter die Haube geschaut

Instanzvariablen werden im Inneren des Objekts verborgen. Sie sind nicht
so versteckt, dass man sie nicht mehr sieht, wenn man das Objekt
untersucht, und es gibt auch andere Wege, auf sie zuzugreifen, aber Ruby
benutzt den guten objektorientieren Ansatz der Datenkapselung.

Welche Methoden existieren nun für Greeter-Objekte?

<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">Greeter</span><span class="p">.</span><span class="nf">instance_methods</span>
<span class="p">=&gt;</span>
<span class="p">[</span><span class="ss">:sag_hallo</span><span class="p">,</span> <span class="ss">:sag_tschuess</span><span class="p">,</span> <span class="ss">:to_yaml</span><span class="p">,</span> <span class="ss">:to_json</span><span class="p">,</span>
 <span class="ss">:pretty_print</span><span class="p">,</span> <span class="ss">:pretty_print_inspect</span><span class="p">,</span> <span class="ss">:pretty_print_cycle</span><span class="p">,</span>
 <span class="ss">:pretty_print_instance_variables</span><span class="p">,</span> <span class="ss">:Namespace</span><span class="p">,</span>
 <span class="ss">:singleton_class</span><span class="p">,</span> <span class="ss">:dup</span><span class="p">,</span> <span class="ss">:itself</span><span class="p">,</span> <span class="ss">:methods</span><span class="p">,</span>
 <span class="ss">:singleton_methods</span><span class="p">,</span> <span class="ss">:protected_methods</span><span class="p">,</span> <span class="ss">:private_methods</span><span class="p">,</span>
 <span class="ss">:public_methods</span><span class="p">,</span> <span class="ss">:instance_variables</span><span class="p">,</span> <span class="ss">:instance_variable_get</span><span class="p">,</span>
 <span class="ss">:instance_variable_set</span><span class="p">,</span> <span class="ss">:instance_variable_defined?</span><span class="p">,</span>
 <span class="ss">:remove_instance_variable</span><span class="p">,</span> <span class="ss">:instance_of?</span><span class="p">,</span> <span class="ss">:kind_of?</span><span class="p">,</span> <span class="ss">:is_a?</span><span class="p">,</span>
 <span class="ss">:display</span><span class="p">,</span> <span class="ss">:TypeName</span><span class="p">,</span> <span class="ss">:public_send</span><span class="p">,</span> <span class="ss">:extend</span><span class="p">,</span> <span class="ss">:clone</span><span class="p">,</span> <span class="ss">:&lt;=&gt;</span><span class="p">,</span>
 <span class="ss">:===</span><span class="p">,</span> <span class="ss">:class</span><span class="p">,</span> <span class="p">:</span><span class="o">!~</span><span class="p">,</span> <span class="ss">:tap</span><span class="p">,</span> <span class="ss">:frozen?</span><span class="p">,</span> <span class="ss">:yield_self</span><span class="p">,</span> <span class="ss">:then</span><span class="p">,</span> <span class="ss">:nil?</span><span class="p">,</span>
 <span class="ss">:eql?</span><span class="p">,</span> <span class="ss">:respond_to?</span><span class="p">,</span> <span class="ss">:method</span><span class="p">,</span> <span class="ss">:public_method</span><span class="p">,</span> <span class="ss">:singleton_method</span><span class="p">,</span>
 <span class="ss">:define_singleton_method</span><span class="p">,</span> <span class="ss">:hash</span><span class="p">,</span> <span class="ss">:freeze</span><span class="p">,</span> <span class="ss">:inspect</span><span class="p">,</span> <span class="ss">:object_id</span><span class="p">,</span>
 <span class="ss">:send</span><span class="p">,</span> <span class="ss">:to_s</span><span class="p">,</span> <span class="ss">:pretty_inspect</span><span class="p">,</span> <span class="ss">:to_enum</span><span class="p">,</span> <span class="ss">:enum_for</span><span class="p">,</span> <span class="ss">:equal?</span><span class="p">,</span> <span class="p">:</span><span class="o">!</span><span class="p">,</span>
 <span class="ss">:__send__</span><span class="p">,</span> <span class="ss">:==</span><span class="p">,</span> <span class="p">:</span><span class="o">!=</span><span class="p">,</span> <span class="ss">:instance_eval</span><span class="p">,</span> <span class="ss">:instance_exec</span><span class="p">,</span> <span class="ss">:__id__</span><span class="p">]</span></code></pre></figure>

Hoppla, das sind aber ganz schön viele! Wir haben doch nur zwei Methoden
definiert. Was ist hier also los? Es handelt sich hier um **alle**
Methoden für das Greeter-Objekt – die komplette Liste – inklusive der
Methoden, die von Eltern-Klassen definiert wurden. Wenn wir nur die
Methoden auflisten wollen, die für Greeter definiert wurden, können wir
aber festlegen, dass die Eltern-Klassen nicht berücksichtigt werden
sollen, indem wir `false` als Parameter angeben.

<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">Greeter</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">"sag_hallo"</span><span class="p">,</span> <span class="s2">"sag_tschuess"</span><span class="p">]</span></code></pre></figure>

Aha, das sieht schon besser aus! Nun schauen wir mal, auf welche
Methoden unser Greeter-Objekt reagiert:

<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">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"name"</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">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"sag_hallo"</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">g</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>

Es kennt also `sag_hallo` und `to_s`. (Die zuletzt genannte Methode ist
jedem Objekt per Voreinstellung bekannt – sie wandelt etwas in einen
String um.) Aber es kennt nicht `name`.

## Für Klassen-Veränderungen ist es nie zu spät

Aber was, wenn wir es ermöglichen wollen, dass man den Namen ansehen
oder ändern kann? Ruby liefert eine einfache Möglichkeit, Zugriff auf
die Variablen eines Objekts zu gewähren.

<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">Greeter</span>
<span class="gp">irb(main):045:1&gt;</span><span class="w">   </span><span class="nb">attr_accessor</span> <span class="ss">:name</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">:name</span><span class="p">,</span> <span class="ss">:name</span><span class="o">=</span><span class="p">]</span></code></pre></figure>

In Ruby kann man eine Klasse jederzeit verändern. Die Änderungen werden
in sämtlichen neu erzeugten Objekten vorhanden sein und darüber hinaus
sogar von bereits existenten Objekten übernommen. Erzeugen wir also ein
neues Objekt und spielen ein bisschen mit dessen `@name`-Eigenschaft
herum.

<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">g</span> <span class="o">=</span> <span class="no">Greeter</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"Andreas"</span><span class="p">)</span>
<span class="gp">=&gt; #&lt;Greeter:0x3c9b0 @name="Andreas"&gt;</span><span class="w">
</span><span class="gp">irb(main):048:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"name"</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">g</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="s2">"name="</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">g</span><span class="p">.</span><span class="nf">sag_hallo</span>
<span class="go">Hallo, Andreas!
</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">g</span><span class="p">.</span><span class="nf">name</span><span class="o">=</span><span class="s2">"Bettina"</span>
<span class="p">=&gt;</span> <span class="s2">"Bettina"</span>
<span class="gp">irb(main):052:0&gt;</span><span class="w"> </span><span class="n">g</span>
<span class="gp">=&gt; #&lt;Greeter:0x3c9b0 @name="Bettina"&gt;</span><span class="w">
</span><span class="gp">irb(main):053:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">name</span>
<span class="p">=&gt;</span> <span class="s2">"Bettina"</span>
<span class="gp">irb(main):054:0&gt;</span><span class="w"> </span><span class="n">g</span><span class="p">.</span><span class="nf">sag_hallo</span>
<span class="go">Hallo, Bettina!
</span><span class="p">=&gt;</span> <span class="kp">nil</span></code></pre></figure>

Die Benutzung von `attr_accessor` hat zwei neue Methoden für uns
definiert: Mit `name` erhält man den Wert, mit `name=` setzt man ihn.

## Die Begrüßung von allem und jedem – MegaGreeter vernachlässigt niemanden!

Die Greeter-Klasse ist nicht unbedingt interessant, sie kann nur eine
Person gleichzeitig behandeln. Was, wenn wir eine Art MegaGreeter
hätten, der entweder die ganze Welt, eine Person oder eine Liste von
Leuten begrüßen könnte?

Schreiben wir das lieber in eine Textdatei, statt es direkt in den
interaktiven Ruby-Interpreter IRB zu tippen.

Um IRB zu beenden, gib “quit” oder “exit” ein, oder drücke einfach
Strg-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">MegaGreeter</span>
  <span class="nb">attr_accessor</span> <span class="ss">:names</span>

  <span class="c1"># Erzeuge das Objekt</span>
  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">names</span> <span class="o">=</span> <span class="s2">"Welt"</span><span class="p">)</span>
    <span class="vi">@names</span> <span class="o">=</span> <span class="n">names</span>
  <span class="k">end</span>

  <span class="c1"># Sag Hallo zu allen</span>
  <span class="k">def</span> <span class="nf">sag_hallo</span>
    <span class="k">if</span> <span class="vi">@names</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">@names</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"># @names ist eine Liste, durchlaufe sie!</span>
      <span class="vi">@names</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="nb">name</span><span class="o">|</span>
        <span class="nb">puts</span> <span class="s2">"Hallo, </span><span class="si">#{</span><span class="nb">name</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">"Hallo, </span><span class="si">#{</span><span class="vi">@names</span><span class="si">}</span><span class="s2">!"</span>
    <span class="k">end</span>
  <span class="k">end</span>

  <span class="c1"># Sag Tschuess zu allen</span>
  <span class="k">def</span> <span class="nf">sag_tschuess</span>
    <span class="k">if</span> <span class="vi">@names</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">@names</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"># Verbinde die Listenelemente mit einem Komma</span>
      <span class="nb">puts</span> <span class="s2">"Tschuess, </span><span class="si">#{</span><span class="vi">@names</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">, bis bald!"</span>
    <span class="k">else</span>
      <span class="nb">puts</span> <span class="s2">"Tschuess, </span><span class="si">#{</span><span class="vi">@names</span><span class="si">}</span><span class="s2">, bis bald!"</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">mg</span> <span class="o">=</span> <span class="no">MegaGreeter</span><span class="p">.</span><span class="nf">new</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">sag_hallo</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">sag_tschuess</span>

  <span class="c1"># Aendere den Namen in "Maximilian"</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">names</span> <span class="o">=</span> <span class="s2">"Maximilian"</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">sag_hallo</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">sag_tschuess</span>

  <span class="c1"># Aendere den Namen in ein Array von Namen</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">names</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Albert"</span><span class="p">,</span> <span class="s2">"Bianca"</span><span class="p">,</span> <span class="s2">"Carl-Heinz"</span><span class="p">,</span>
    <span class="s2">"David"</span><span class="p">,</span> <span class="s2">"Engelbert"</span><span class="p">]</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">sag_hallo</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">sag_tschuess</span>

  <span class="c1"># Aendere in nil</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">names</span> <span class="o">=</span> <span class="kp">nil</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">sag_hallo</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">sag_tschuess</span>
<span class="k">end</span></code></pre></figure>

Speichere diese Textdatei als “ri20min.rb” und starte es mit “ruby
ri20min.rb”. Die Ausgabe sollte sein:

    Hallo, Welt!
    Tschuess, Welt, bis bald!
    Hallo, Maximilian!
    Tschuess, Maximilian, bis bald!
    Hallo, Albert!
    Hallo, Bianca!
    Hallo, Carl-Heinz!
    Hallo, David!
    Hallo, Engelbert!
    Tschuess, Albert, Bianca, Carl-Heinz, David, Engelbert, bis bald!
    ...
    ...
{: .code}

In dieses Beispiel wurden einige neue Dinge gestreut, auf die wir
sogleich [näher eingehen werden](../4/).
