Gdy po raz pierwszy zobaczysz kawałek kodu w Rubim, prawdopodobnie
będzie on zbliżony do innych języków, z którymi miałeś do czynienia. Tak
ma być. Większość składni nawiązuje do Perla, Pythona i Javy, więc jeśli
te języki są znajome, to nauka Rubiego będzie jak bułka z masłem.
{: .summary}

Ten dokument zawiera dwie sekcje. Pierwsza, opisuje najważniejsze
różnice pomiędzy językiem *X* a Rubim. Druga zawiera obraz
najważniejszych elementów języka i porównuje je do tego, co już znasz.

## Czego oczekiwać: *Język X* a Ruby

* [Ruby a Java](to-ruby-from-java/)
* [Ruby a PHP](to-ruby-from-php/)
* [Ruby a Python](to-ruby-from-python/)

## Ważne elementy języka i niespodzianki

Poniżej znajdziesz kilka wskazówek na temat najważniejszych elementów
Rubiego.

### Iteracja

Są dwa elementy, które są nieco różne od tego co możesz już znać. Jednym
z nich są “bloki” oraz iteratory. Zamiast iterować po indeksach w
tablicy (jak w C, C++ lub Javie &lt; 1.5), lub przechodzić po pętli po
liście (jak w Perlowym `for (@a) {...}`, lub Pythonowym
`for i in lista: ...`), w Rubim zobaczysz:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">lista</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">element</span><span class="o">|</span>
  <span class="c1"># Jesteśmy w bloku.</span>
  <span class="c1"># Tutaj zajmujemy się element-em.</span>
<span class="k">end</span></code></pre></figure>

Aby dowiedzieć się więcej o `each` (oraz pokrewnych: `collect`, `find`,
`inject`, `sort`, itd), rzuć okiem na `ri Enumerable`
(a potem `ri Enumerable#func_name`).

### Wszystko ma wartość

Nie ma różnicy pomiędzy wyrażeniem a instrukcją. Wszystko posiada
wartość, nawet jeśli ta wartość jest **nil**.

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">x</span> <span class="o">=</span> <span class="mi">10</span>
<span class="n">y</span> <span class="o">=</span> <span class="mi">11</span>
<span class="n">z</span> <span class="o">=</span> <span class="k">if</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">y</span>
      <span class="kp">true</span>
    <span class="k">else</span>
      <span class="kp">false</span>
    <span class="k">end</span>
<span class="n">z</span> <span class="c1"># =&gt; true</span></code></pre></figure>

### Symbole nie są “lekkimi stringami”

Wielu programistów przechodzących do Rubiego ma problemy ze zrozumieniem
koncepcji symboli, oraz do czego powinno się ich używać.

Symbole są podobną klasą obiektów, co liczby. Każde wystąpienie tej
samej liczby w wyrażeniu zawsze odnosi się do tego samego obiektu.
Spójrz na ten przykład:

<figure class="highlight"><pre><code class="language-irb" data-lang="irb"><span class="gp">irb(main):001:0&gt;</span><span class="w"> </span><span class="ss">:george</span><span class="p">.</span><span class="nf">object_id</span> <span class="o">==</span> <span class="ss">:george</span><span class="p">.</span><span class="nf">object_id</span>
<span class="p">=&gt;</span> <span class="kp">true</span>
<span class="gp">irb(main):002:0&gt;</span><span class="w"> </span><span class="s2">"george"</span><span class="p">.</span><span class="nf">object_id</span> <span class="o">==</span> <span class="s2">"george"</span><span class="p">.</span><span class="nf">object_id</span>
<span class="p">=&gt;</span> <span class="kp">false</span>
<span class="gp">irb(main):003:0&gt;</span></code></pre></figure>

Metoda `object_id` zwraca unikalny identyfikator obiektu w pamięci.
Jeśli dwa obiekty mają ten sam `object_id`, to są tym samym obiektem
(lub wskazują na ten sam obiekt w pamięci).

Jeśli zatem użyjesz raz jakiegoś symbolu, to kolejne odwołania do niego,
zawsze będą odnosić się do tego samego obiektu. Każde dwa symbole
reprezentujące ten sam ciąg znaków wskazują na ten sam obiekt w pamięci.
Ich `object_id` pasują do siebie.

Spójrzmy na String (“george”). Wartości `object_id` nie są te same.
Znaczy to tyle, że odnosimy się do dwóch osobnych obiektów w pamięci.
Kiedykolwiek używasz Stringów, Ruby dla każdego z nich alokuje pamięć.

Jeśli nie jesteś pewien w jakim scenariuszu użyć Symbolu a w jakim
Stringa, zastanów się co w danym przypadku jest istotne — tożsamość
obiektu (na przykład w słowniku), czy jego wartość (“george”).

### Wszystko jest obiektem.

“Wszystko jest obiektem” to bardzo silne założenie. Nawet klasy i liczby
całkowite są obiektami, i możesz na nich działać jak na zwykłych
obiektach:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># Poniższe definicje są tożsame</span>
<span class="c1"># class MyClass</span>
<span class="c1">#   attr_accessor :instance_var</span>
<span class="c1"># end</span>
<span class="no">MyClass</span> <span class="o">=</span> <span class="no">Class</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
  <span class="nb">attr_accessor</span> <span class="ss">:instance_var</span>
<span class="k">end</span></code></pre></figure>

### Stałe (zmienne)

Stałe tak naprawdę nie są stałymi. Jeśli zmodyfikujesz stałą, która już
posiada wartość, otrzymasz ostrzeżenie, ale nie doprowadzi to do
wstrzymania twojego programu. Nie znaczy to oczywiście, że powinieneś
modyfikować wartość stałych.

### Konwencje nazewnictwa

Ruby wymusza pewną konwencję jeśli chodzi o nazewnictwo. Jeśli nazwa
zaczyna się od wielkiej litery, jest stałą. Jeśli zaczyna się od znaku
dolara (`$`), jest zmienną globalną. Jeśli zaczyna się od `@`, jest
zmienną należącą do egzemplarza obiektu. Jeśli zaczyna się od `@@`, jest
zmienną należącą do klasy.

Nazwy metod mogą zaczynać się od wielkiej litery. Może być to źródłem
pewnego zamieszania, jak widać poniżej:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="no">Constant</span> <span class="o">=</span> <span class="mi">10</span>
<span class="k">def</span> <span class="nf">Constant</span>
  <span class="mi">11</span>
<span class="k">end</span></code></pre></figure>

Teraz `Constant` ma wartość 10, ale `Constant()` daje wartość 11.

### Argumenty z kluczem

Tak jak w Pythonie, od wersji Rubiego 2.0 metody można definiować
przy użyciu argumentów z kluczem:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">deliver</span><span class="p">(</span><span class="ss">from: </span><span class="s2">"A"</span><span class="p">,</span> <span class="ss">to: </span><span class="kp">nil</span><span class="p">,</span> <span class="ss">via: </span><span class="s2">"mail"</span><span class="p">)</span>
  <span class="s2">"Wyślij od </span><span class="si">#{</span><span class="n">from</span><span class="si">}</span><span class="s2"> do </span><span class="si">#{</span><span class="n">to</span><span class="si">}</span><span class="s2"> poprzez </span><span class="si">#{</span><span class="n">via</span><span class="si">}</span><span class="s2">."</span>
<span class="k">end</span>

<span class="n">deliver</span><span class="p">(</span><span class="ss">to: </span><span class="s2">"B"</span><span class="p">)</span>
<span class="c1"># =&gt; "Wyślij od A do B poprzez mail."</span>
<span class="n">deliver</span><span class="p">(</span><span class="ss">via: </span><span class="s2">"Pony Express"</span><span class="p">,</span> <span class="ss">from: </span><span class="s2">"B"</span><span class="p">,</span> <span class="ss">to: </span><span class="s2">"A"</span><span class="p">)</span>
<span class="c1"># =&gt; "Wyślij od B do A poprzez Pony Express."</span></code></pre></figure>

### Prawda absolutna

W Rubim wszystko, oprócz **nil** oraz **false** jest równoważne
**true**. W C, Pythonie i wielu innych językach, zero oraz inne
wartości, takie jak puste listy są uważane za **false**. Spójrz na
poniższy kod w Pythonie:

<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1"># w Pythonie
</span><span class="k">if</span> <span class="mi">0</span><span class="p">:</span>
  <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">0 is true</span><span class="sh">"</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
  <span class="nf">print</span><span class="p">(</span><span class="sh">"</span><span class="s">0 is false</span><span class="sh">"</span><span class="p">)</span></code></pre></figure>

Ten kawałek kodu wypisze `0 is false` To samo w Rubim wygląda
tak:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># w Rubim</span>
<span class="k">if</span> <span class="mi">0</span>
  <span class="nb">puts</span> <span class="s2">"0 is true"</span>
<span class="k">else</span>
  <span class="nb">puts</span> <span class="s2">"0 is false"</span>
<span class="k">end</span></code></pre></figure>

Wypisze “0 is true”.

### Modyfikatory zakresu dostępu do metod działają do końca definicji klasy.

W poniższym kodzie,

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">MyClass</span>
  <span class="kp">private</span>
  <span class="k">def</span> <span class="nf">a_method</span><span class="p">;</span> <span class="kp">true</span><span class="p">;</span> <span class="k">end</span>
  <span class="k">def</span> <span class="nf">another_method</span><span class="p">;</span> <span class="kp">false</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

Być może oczekujesz, że `another_method` jest metodą publiczną? Nie
jest. Modyfikator dostępu `private` jest zastosowany dla wszystkich
metod następujących po nim, lub do momentu napotkania innego
modyfikatora zakresu dostępu. Domyślnie, wszystkie metody są publiczne.

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">MyClass</span>
  <span class="c1"># Now a_method is public</span>
  <span class="k">def</span> <span class="nf">a_method</span><span class="p">;</span> <span class="kp">true</span><span class="p">;</span> <span class="k">end</span>

  <span class="kp">private</span>

  <span class="c1"># another_method jest metodą prywatną</span>
  <span class="k">def</span> <span class="nf">another_method</span><span class="p">;</span> <span class="kp">false</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

`public`, `private` and `protected` to tak naprawdę metody, mogą więc przyjmować parametry. Jeśli tym metodom przekażesz Symbol jako parametr, zmienisz widoczność danej metody.

### Dostęp do metod

W Javie, `public` oznacza, że dana metoda jest dostępna dla wszystkich.
`protected` oznacza, że dostęp mają instancje danej klasy i klas
pochodnych, natomiast `private` oznacza, że jedynie instancje danej
klasy mają dostęp do danej metody.

Ruby różni się odrobinę w tym względzie. `public` oznacza tak samo
dostęp publiczny. `private` oznacza, że dana metoda(y) jest dostępna
tylko wtedy, jeśli można ją wywołać bez wyraźnego określenia odbiorcy.
Jedynie **self** jest dozwolonym odbiorcą wywołań prywatnych metod.

`protected` jest tym, na co trzeba zwrócić uwagę. Metoda chroniona może być wywołana przez instancje danej klasy lub klas pochodnych, ale również przez inną instancję danej klasy. Poniżej przykład za [Ruby Language FAQ][faq]:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">Test</span>
  <span class="c1"># domyślnie metoda publiczna</span>
  <span class="k">def</span> <span class="nf">identifier</span>
    <span class="mi">99</span>
  <span class="k">end</span>

  <span class="k">def</span> <span class="nf">==</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
    <span class="n">identifier</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="nf">identifier</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="n">t1</span> <span class="o">=</span> <span class="no">Test</span><span class="p">.</span><span class="nf">new</span>  <span class="c1"># =&gt; #&lt;Test:0x34ab50&gt;</span>
<span class="n">t2</span> <span class="o">=</span> <span class="no">Test</span><span class="p">.</span><span class="nf">new</span>  <span class="c1"># =&gt; #&lt;Test:0x342784&gt;</span>
<span class="n">t1</span> <span class="o">==</span> <span class="n">t2</span>       <span class="c1"># =&gt; true</span>

<span class="c1"># uczyńmy teraz `identifier' metodą chronioną, wciąż działa</span>
<span class="c1"># ponieważ 'protected' umożliwia odniesienie do `other'</span>

<span class="k">class</span> <span class="nc">Test</span>
  <span class="kp">protected</span> <span class="ss">:identifier</span>
<span class="k">end</span>

<span class="n">t1</span> <span class="o">==</span> <span class="n">t2</span>  <span class="c1"># =&gt; true</span>

<span class="c1"># uczyńmy teraz `identifier' metodą prywatną</span>

<span class="k">class</span> <span class="nc">Test</span>
  <span class="kp">private</span> <span class="ss">:identifier</span>
<span class="k">end</span>

<span class="n">t1</span> <span class="o">==</span> <span class="n">t2</span>
<span class="c1"># NoMethodError: private method `identifier' called for #&lt;Test:0x342784&gt;</span></code></pre></figure>

### Klasy są otwarte

Klasy Rubiego są otwarte. Można je otworzyć, dodać nowe metody czy
zmienić istniejące działanie w dowolnym momencie. Nawet główne klasy
takie jak `Integer` czy nawet `Object`, rodzic wszystkich obiektów. Ruby
on Rails na przykład definiuje zestaw metod do operowania czasem w
klasie `Integer`. Poniżej:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">Integer</span>
  <span class="k">def</span> <span class="nf">hours</span>
    <span class="nb">self</span> <span class="o">*</span> <span class="mi">3600</span> <span class="c1"># liczba sekund w godzinie</span>
  <span class="k">end</span>
  <span class="k">alias</span> <span class="n">hour</span> <span class="n">hours</span>
<span class="k">end</span>

<span class="c1"># 14 hours from 00:00 January 1st</span>
<span class="c1"># (czyt. kiedy w końcu się obudzisz ;)</span>
<span class="no">Time</span><span class="p">.</span><span class="nf">mktime</span><span class="p">(</span><span class="mi">2006</span><span class="p">,</span> <span class="mo">01</span><span class="p">,</span> <span class="mo">01</span><span class="p">)</span> <span class="o">+</span> <span class="mi">14</span><span class="p">.</span><span class="nf">hours</span> <span class="c1"># =&gt; Sun Jan 01 14:00:00</span></code></pre></figure>

### Śmieszne nazwy metod

W Rubim, nazwy metod mogą kończyć się pytajnikiem lub wykrzyknikiem.
Według przyjętej konwencji, metody które odpowiadają na jakieś pytanie
(n.p. `Array#empty?` zwraca **true** jeśli odbiorca jest pusty)
kończą się pytajnikiem. Potencjalnie “groźne” metody (np. metody, które
modyfikują **self** – dany obiekt lub swoje argumenty `exit!` etc.)
kończą się wykrzyknikiem.

Wszystkie metody, których celem jest zmiana swoich argumentów, nie
kończą się wykrzyknikiem. `Array#replace` zamienia zawartość
danej tablicy zawartością innej tablicy. Istnienie tej metody w celu
innym niż modyfikacja danego obiektu **self** nie ma zbyt dużego sensu.

### Metody singleton

Metody singletonowe to metody, które zostały zdefiniowane i są dostępne
dla danego obiektu.

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">Car</span>
  <span class="k">def</span> <span class="nf">inspect</span>
    <span class="s2">"Tani samochód"</span>
  <span class="k">end</span>
<span class="k">end</span>

<span class="n">porsche</span> <span class="o">=</span> <span class="no">Car</span><span class="p">.</span><span class="nf">new</span>
<span class="n">porsche</span><span class="p">.</span><span class="nf">inspect</span> <span class="c1"># =&gt; Tani samochód</span>
<span class="k">def</span> <span class="nc">porsche</span><span class="o">.</span><span class="nf">inspect</span>
  <span class="s2">"Drogi samochód"</span>
<span class="k">end</span>

<span class="n">porsche</span><span class="p">.</span><span class="nf">inspect</span> <span class="c1"># =&gt; Drogi samochód</span>

<span class="c1"># Inne obiekty nie zostały zmienione</span>
<span class="n">other_car</span> <span class="o">=</span> <span class="no">Car</span><span class="p">.</span><span class="nf">new</span>
<span class="n">other_car</span><span class="p">.</span><span class="nf">inspect</span> <span class="c1"># =&gt; Tani samochód</span></code></pre></figure>

### Brakujące metody

Ruby nie poddaje się jeśli nie może odnaleźć danej metody. Wywołuje w
takim przypadku metodę `method_missing` przekazując nazwę metody, której
nie mógł znaleźć jako argument. Domyślnie, `method_missing` zgłasza
wyjątek NameError, lecz można ją przedefiniować aby lepiej pasowała do
Twojej aplikacji, wiele bibliotek tak robi. Poniżej jeden z przykładów:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># id jest nazwą wywołanej metody, składnia * łączy wszystkie pozostałe argumenty</span>
<span class="c1"># w tablicę nazwaną 'arguments'</span>
<span class="k">def</span> <span class="nf">method_missing</span><span class="p">(</span><span class="nb">id</span><span class="p">,</span> <span class="o">*</span><span class="n">arguments</span><span class="p">)</span>
  <span class="nb">puts</span> <span class="s2">"Wywołano niezdefiniowaną metodę </span><span class="si">#{</span><span class="nb">id</span><span class="si">}</span><span class="s2">. Przekazano "</span> <span class="o">+</span>
       <span class="s2">"poniższe argumenty: </span><span class="si">#{</span><span class="n">arguments</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">"</span>
<span class="k">end</span>

<span class="n">__</span> <span class="ss">:a</span><span class="p">,</span> <span class="ss">:b</span><span class="p">,</span> <span class="mi">10</span>
<span class="c1"># =&gt; Wywołano niezdefiniowaną metodę __. Przekazano poniższe</span>
<span class="c1"># argumenty: a, b, 10</span></code></pre></figure>

Powyższy kod wyświetla po prostu szczegóły wywołania, możesz to
zachowanie dowolnie zmienić.

### Przekazywanie wiadomości, nie wywołanie metody

Wywołanie metody jest tak naprawdę **wiadomością** przekazywaną innemu
obiektowi:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="c1"># To</span>
<span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span>
<span class="c1"># Jest to samo co ...</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">+</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="c1"># Jest to to samo co:</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">send</span> <span class="s2">"+"</span><span class="p">,</span> <span class="mi">2</span></code></pre></figure>

### Bloki są Obiektami, tylko o tym jeszcze nie wiedzą

Bloki (tak naprawdę domknięcia) są powszechnie używane w podstawowej
bibliotece Rubiego. Aby wywołać blok, możesz użyć albo `yield`, albo
utworzyć specjalny obiekt typu `Proc` przekazując specjalny argument,
tak jak w poniższym przykładzie:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">block</span><span class="p">(</span><span class="o">&amp;</span><span class="n">the_block</span><span class="p">)</span>
  <span class="c1"># Tutaj, the_block jest blokiem przekazanym do tej metody</span>
  <span class="n">the_block</span> <span class="c1"># zwróć blok</span>
<span class="k">end</span>
<span class="n">adder</span> <span class="o">=</span> <span class="n">block</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span> <span class="p">}</span>
<span class="c1"># adder to teraz obiekt typu Proc</span>
<span class="n">adder</span><span class="p">.</span><span class="nf">class</span> <span class="c1"># =&gt; Proc</span></code></pre></figure>

Możesz tworzyć bloki również poza wywołaniami metod, wywołując `Proc.new`
lub metodę `lambda`.

Podobnie, metody to także obiekty:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">method</span><span class="p">(</span><span class="ss">:puts</span><span class="p">).</span><span class="nf">call</span> <span class="s2">"puts to obiekt!"</span>
<span class="c1"># =&gt; puts to obiekt!</span></code></pre></figure>

### Operatory to cukier syntaktyczny

Większość operatorów w Rubim to po prostu cukier syntaktyczny dla
wywołań metod. Możesz, na przykład, nadpisać metodę + klasy Integer:

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">Integer</span>
  <span class="c1"># Możesz, ale proszę nie rób tego !</span>
  <span class="k">def</span> <span class="nf">+</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
    <span class="nb">self</span> <span class="o">-</span> <span class="n">other</span>
  <span class="k">end</span>
<span class="k">end</span></code></pre></figure>

Nie potrzebujesz operatora z C++’s `operator+`, etc.

Możesz nawet mieć operator tablicowy, o ile zdefiniujesz metody `[]` and `[]=`.
By zdefiniować jednoskładnikowy + i – (tak jak +1 i -2), musisz zdefiniować
odpowiednio metody `+@` i `-@`. Poniższe operatory jednak
**nie są cukrem syntaktycznym**. Nie są metodami dlatego nie można ich
przedefiniować.

<figure class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="o">=</span><span class="p">,</span> <span class="o">..</span><span class="p">,</span> <span class="o">...</span><span class="p">,</span> <span class="ow">not</span><span class="p">,</span> <span class="o">&amp;&amp;</span><span class="p">,</span> <span class="ow">and</span><span class="p">,</span> <span class="o">||</span><span class="p">,</span> <span class="ow">or</span><span class="p">,</span> <span class="o">::</span></code></pre></figure>

Dodatkowo, `+=`, `*=` etc. są po prostu skrótami dla `var = var + other_var`,
`var = var * other_var`, etc. dlatego też nie można ich przedefiniować.

## Więcej

Więcej informacji na temat języka Ruby znajdziesz w
[dokumentacji](/pl/documentation/).



[faq]: http://ruby-doc.org/docs/ruby-doc-bundle/FAQ/FAQ.html
