Тепер створімо об’єкт привітальника та використаємо його:

<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">greeter</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">"Pat"</span><span class="p">)</span>
<span class="gp">=&gt; #&lt;Greeter:0x16cac @name="Pat"&gt;</span><span class="w">
</span><span class="gp">irb(main):036:0&gt;</span><span class="w"> </span><span class="n">greeter</span><span class="p">.</span><span class="nf">say_hi</span>
<span class="go">Hi Pat!
</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">greeter</span><span class="p">.</span><span class="nf">say_bye</span>
<span class="go">Bye Pat, come back soon.
</span><span class="p">=&gt;</span> <span class="kp">nil</span></code></pre></figure>

Після створення об’єкта `greeter` він запам’ятовує, що ім’я — Pat. Гм,
а що, якщо ми хочемо отримати ім’я безпосередньо?

<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">greeter</span><span class="o">.</span><span class="vi">@name</span>
<span class="gr">SyntaxError: (irb):38: syntax error, unexpected tIVAR, expecting '('</span></code></pre></figure>

Ні, так не вийде.

## Під «шкірою» об’єкта

Змінні екземпляра приховані всередині об’єкта. Вони не надто приховані:
ви бачите їх, коли інспектуєте об’єкт, і є інші способи доступу до них,
але Ruby застосовує правильний об’єктно-орієнтований підхід — тримати дані
певною мірою прихованими.

Отже, які методи існують для об’єктів Greeter?

<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">:say_hi</span><span class="p">,</span> <span class="ss">:say_bye</span><span class="p">,</span> <span class="ss">:instance_of?</span><span class="p">,</span> <span class="ss">:public_send</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">:private_methods</span><span class="p">,</span> <span class="ss">:kind_of?</span><span class="p">,</span> <span class="ss">:instance_variables</span><span class="p">,</span> <span class="ss">:tap</span><span class="p">,</span>
    <span class="ss">:is_a?</span><span class="p">,</span> <span class="ss">:extend</span><span class="p">,</span> <span class="ss">:define_singleton_method</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">:&lt;=&gt;</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="p">:</span><span class="o">!~</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">:freeze</span><span class="p">,</span> <span class="ss">:inspect</span><span class="p">,</span> <span class="ss">:display</span><span class="p">,</span> <span class="ss">:send</span><span class="p">,</span> <span class="ss">:object_id</span><span class="p">,</span> <span class="ss">:to_s</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">:nil?</span><span class="p">,</span> <span class="ss">:hash</span><span class="p">,</span>
    <span class="ss">:class</span><span class="p">,</span> <span class="ss">:singleton_class</span><span class="p">,</span> <span class="ss">:clone</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">:taint</span><span class="p">,</span>
    <span class="ss">:tainted?</span><span class="p">,</span> <span class="ss">:untaint</span><span class="p">,</span> <span class="ss">:untrust</span><span class="p">,</span> <span class="ss">:trust</span><span class="p">,</span> <span class="ss">:untrusted?</span><span class="p">,</span> <span class="ss">:methods</span><span class="p">,</span>
    <span class="ss">:protected_methods</span><span class="p">,</span> <span class="ss">:frozen?</span><span class="p">,</span> <span class="ss">:public_methods</span><span class="p">,</span> <span class="ss">:singleton_methods</span><span class="p">,</span>
    <span class="p">:</span><span class="o">!</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">:__send__</span><span class="p">,</span> <span class="ss">:equal?</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>

Ого. Це багато методів. Ми визначили лише два. Що відбувається?
Насправді це **всі** методи об’єктів Greeter — повний список, включно
з методами, визначеними у класах-предках. Якщо ми хочемо побачити лише
методи, визначені саме для Greeter, можемо вказати, що не потрібно
включати предків, передавши параметр `false`.

<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="ss">:say_hi</span><span class="p">,</span> <span class="ss">:say_bye</span><span class="p">]</span></code></pre></figure>

О, це вже краще. Тепер подивімося, на які методи реагує наш об’єкт greeter:

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

Отже, він знає `say_hi` і `to_s` (тобто перетворення на рядок — метод,
визначений за замовчуванням для кожного об’єкта), але не знає `name`.

## Зміна класів — ніколи не пізно

А що, якщо ви хочете мати доступ до імені або змінювати його? Ruby
надає простий спосіб доступу до змінних об’єкта.

<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>

У Ruby можна знову відкрити клас і змінити його. Зміни будуть доступні
для нових об’єктів і навіть для вже існуючих об’єктів цього класу.
Тож створімо новий об’єкт і пограємося з його властивістю `@name`.

<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">greeter</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">"Andy"</span><span class="p">)</span>
<span class="gp">=&gt; #&lt;Greeter:0x3c9b0 @name="Andy"&gt;</span><span class="w">
</span><span class="gp">irb(main):048:0&gt;</span><span class="w"> </span><span class="n">greeter</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">greeter</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">greeter</span><span class="p">.</span><span class="nf">say_hi</span>
<span class="go">Hi Andy!
</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">greeter</span><span class="p">.</span><span class="nf">name</span><span class="o">=</span><span class="s2">"Betty"</span>
<span class="p">=&gt;</span> <span class="s2">"Betty"</span>
<span class="gp">irb(main):052:0&gt;</span><span class="w"> </span><span class="n">greeter</span>
<span class="gp">=&gt; #&lt;Greeter:0x3c9b0 @name="Betty"&gt;</span><span class="w">
</span><span class="gp">irb(main):053:0&gt;</span><span class="w"> </span><span class="n">greeter</span><span class="p">.</span><span class="nf">name</span>
<span class="p">=&gt;</span> <span class="s2">"Betty"</span>
<span class="gp">irb(main):054:0&gt;</span><span class="w"> </span><span class="n">greeter</span><span class="p">.</span><span class="nf">say_hi</span>
<span class="go">Hi Betty!
</span><span class="p">=&gt;</span> <span class="kp">nil</span></code></pre></figure>

Використання `attr_accessor` визначило для нас два нові методи: `name`
для отримання значення і `name=` для його встановлення.

## Вітання всього й усіх: MegaGreeter нікого не обділяє!

Цей привітальник не надто цікавий — він може працювати лише з однією
людиною за раз. А що, якщо у нас буде MegaGreeter, який може вітати
світ, одну людину або цілий список людей?

Напишімо це у файлі замість введення безпосередньо в інтерактивний
інтерпретатор Ruby (IRB).

Щоб вийти з IRB, введіть “quit”, “exit” або просто натисніть 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">MegaGreeter</span>
  <span class="nb">attr_accessor</span> <span class="ss">:names</span>

  <span class="c1"># Create the object</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">"World"</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"># Say hi to everybody</span>
  <span class="k">def</span> <span class="nf">say_hi</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 is a list of some kind, iterate!</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">"Hello </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">"Hello </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"># Say bye to everybody</span>
  <span class="k">def</span> <span class="nf">say_bye</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"># Join the list elements with commas</span>
      <span class="nb">puts</span> <span class="s2">"Goodbye </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">.  Come back soon!"</span>
    <span class="k">else</span>
      <span class="nb">puts</span> <span class="s2">"Goodbye </span><span class="si">#{</span><span class="vi">@names</span><span class="si">}</span><span class="s2">.  Come back soon!"</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">say_hi</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_bye</span>

  <span class="c1"># Change name to be "Zeke"</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">names</span> <span class="o">=</span> <span class="s2">"Zeke"</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_hi</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_bye</span>

  <span class="c1"># Change the name to an array of names</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">"Brenda"</span><span class="p">,</span> <span class="s2">"Charles"</span><span class="p">,</span>
              <span class="s2">"Dave"</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">say_hi</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_bye</span>

  <span class="c1"># Change to 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">say_hi</span>
  <span class="n">mg</span><span class="p">.</span><span class="nf">say_bye</span>
<span class="k">end</span></code></pre></figure>

Збережіть цей файл як “ri20min.rb” і запустіть як “ruby ri20min.rb”.
Вивід має бути таким:

    Hello World!
    Goodbye World.  Come back soon!
    Hello Zeke!
    Goodbye Zeke.  Come back soon!
    Hello Albert!
    Hello Brenda!
    Hello Charles!
    Hello Dave!
    Hello Engelbert!
    Goodbye Albert, Brenda, Charles, Dave, Engelbert.  Come
    back soon!
    ...
    ...
{: .code}

У цьому фінальному прикладі з’явилося багато нового, що ми
[можемо розглянути детальніше.](../4/)
