Ruby/Metody: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
Szymon wro (dyskusja | edycje)
Nie podano opisu zmian
Szymon wro (dyskusja | edycje)
Nie podano opisu zmian
Linia 7:
W Rubim wywołujemy metody obiektu posługując się zapisem z kropką (tak jak w C++ lub Javie). Nazwa obiektu do którego mówimy znajduje się na lewo od kropki.
 
<source lang="ruby">
<pre>
ruby> "abcdef".length #=> 6
</source>
6
</pre>
 
Rozumując intuicyjnie, ten łańcuch pytany jest o swoją długość. Technicznie natomiast, wywołujemy metodę <tt>length</tt> na rzecz obiektu <tt>"abcdef"</tt>.
Linia 16 ⟶ 15:
Pozostałe obiekty mogą mieć nieco inną interpretację długości lub nawet nie mieć żadnej. Decyzje dotyczące tego, jak odpowiedzieć na wiadomość podejmowane są w locie, podczas wykonywania programu, i podejmowane działanie może być zmienione w zależności o tego, na co wskazuje zmienna.
 
<source lang="ruby">
<pre>
ruby> fooa = "abc"
puts a.length #=> 3
"abc"
a = ["abcde", "fghij"]
ruby> foo.length
a.length #=> 2
3
</source>
ruby> foo = ["abcde", "fghij"]
["abcde", "fghij"]
ruby> foo.length
2
</pre>
 
To, co rozumiemy przez długość może się różnić w zależności od rodzaju obiektu do którego mówimy. Za pierwszym razem w powyższym przykładzie pytamy <tt>fooa</tt> o jegojej długość i <tt>fooa</tt> wskazuje na prosty łańcuch znakowy, więc jest tylko jedna sensowną odpowiedź. Za drugim razem <tt>fooa</tt> odnosi się do tablicy i możemy rozsądnie myśleć o jej długości jako o 2, 5 lub 10 - oczywiście w tym przypadku jest to 2. RóżnegoRóżne rodzajuobiekty długościmogą możemymieć wyszukaćróżnego wrodzaju różnych obiektach na zawołaniedługości.
 
<source lang="ruby">
<pre
ruby> fooa[0].length #=> 5
ruby> fooa[0].length + fooa[1].length #=> 10
5
</source>
ruby> foo[0].length + foo[1].length
10
</pre>
 
Rzeczą godną uwagi jest to, że tablica wie o sobie to coś, co oznacza, że jest ona tablicą. W Rubim kawałki danych przechowują tę wiedzę. Zatem żądania, które wobec nich kierujemy mogą być automatycznie spełnione na wiele różnych sposobów. Zdejmuje to z programisty brzemię pamiętania olbrzymiej liczby wielu specyficznych nazw funkcji, ponieważ relatywnie mała liczba nazw metod (będących w zgodzie koncepcjami wyrażalnymi w języku naturalnym) może być zastosowane do różnych typów danych. W rezultacie programista otrzymuje to, czego się spodziewał. Ta cecha języków programowania obiektowego nazywana jest ''[[w:Polimorfizm (informatyka)|polimorfizmem]]''.
Linia 40 ⟶ 33:
Kiedy obiekt otrzymuje komunikat, którego nie rozumie, "podnoszony" jest błąd:
 
<source lang="ruby">
<pre>
ruby> fooa = 5
ruby> fooa.length
5
ruby> foo.length
ERR: (eval):1: undefined method `length' for 5(Fixnum)
</presource>
 
Tak więc należy wiedzieć, które metody są akceptowane przez obiekt, chociaż nie trzeba analizować jak są one przetwarzane.
Linia 51 ⟶ 43:
Jeżeli przekazujemy do metody jakieś argumenty, zazwyczaj otaczamy je nawiasami okrągłymi:
 
<source lang="ruby">
<pre>
obiekt.metoda(arg1, arg2)
</presource>
 
Można je pominąć, jeśli, nie stanie się to przyczyną dwuznaczności<ref>Zaleca się jednak pomijanie nawiasów tylko w wywołaniach najprostszych i najbardziej oczywistych metod, jak np. <tt>puts</tt>.</ref>.
 
<source lang="ruby">
<pre>
obiekt.metoda arg1, arg2
</presource>
 
Jest pewna specjalna zmienna w Rubim - '''<tt>self</tt>'''. Odnosi się ona tylko do obiektu na rzecz którego wywołujemy metodę. Dzieje się to tak często, że dla wygody "<tt>self.</tt>" może być opuszczone w metodach odwołujących się z danego obiektu do samego obiektu:
 
<source lang="ruby">
<pre>
self.nazwa_metody(argumenty...)
</presource>
 
oznacza to samo co
 
<source lang="ruby">
<pre>
nazwa_metody(argumenty...)
</presource>
 
To co tradycyjnie nazwalibyśmy wywołaniem funkcji jest po prostu skróconą formą zapisu wywołań metod przez <tt>self</tt>. To właśnie czyni z Rubiego czysto obiektowy język programowania. Ponadto metody funkcyjne nadal zachowują się całkiem podobnie do funkcji w innych językach programowania. Jest to pewnapewne korzyśćułatwienie dla tych, którzyktórym niełatwiej rozumieją,jest że w Rubimtraktować wywołania funkcjimetod jak tak naprawdęwywołania w wywołaniami metod obiektówfunkcji. Jeśli chcemy, możemy, np. w celach edukacyjnych, traktować funkcje tak jakby nie były one naprawdę metodami obiektów.
 
W [[Ruby/Zmienne klasowe|rozdziale]] dotyczącym zmiennych klasowych zobaczyszzobaczymy zastosowanie słowa kluczowego <tt>self</tt> przy definiowaniu metod należących do całej klasy, czyli metod ''klasowych''.
 
Czasami, analizując różne przykłady kodu w Rubim możemy natknąć się na taką definicję metody (albo wywołanie), w której ostatni parametr poprzedzony jest znakiem <tt>*</tt> lub <tt>&</tt>. Dla początkujących może to wyglądać enigmatycznie, a programistów C/C++/C# mogą dodatkowo mylić skojarzenia ze wskaźnikami i referencjami. Obydwa znaki mają jednak zupełnie inne znaczenie, a ponieważ nie ma nic gorszego od kodu, którego nie rozumiemy, wyjaśnijmy znaczenie obu tych symboli.
 
=== <tt>*</tt> czyli zmienna lista argumentów ===
 
Czasami, analizując różne przykłady kodu w Rubim możemy natknąć się na taką definicję metody (albo wywołanie), w której ostatni parametr poprzedzony jest znakiem <tt>*</tt> lub <tt>&</tt>. Dla początkujących może to wyglądać enigmatycznie, a programistów C/C++/C# mogą dodatkowo mylić skojarzenia ze wskaźnikami i referencjami. Obydwa znaki mają jednak zupełnie inne znaczenie, a ponieważ nie ma nic gorszego od kodu, którego nie rozumiemy, wyjaśnijmy znaczenie obu tych symboli.
 
Gwiazdka (<tt>*</tt>) oznacza ''zmienną'' listę argumentów. Jeżeli <tt>*</tt> pojawia się w nagłówku definiowanej metody, poprzedzając ostatni parametr, oznacza to, że począwszy od tego tego argumentu do metody można przekazać dowolną ich ilość. Wszystkie te argumenty są widoczne w metodzie jako tablica.