Ruby/Kontrola dostępu: Różnice pomiędzy wersjami
Usunięta treść Dodana treść
Szymon wro (dyskusja | edycje) |
Szymon wro (dyskusja | edycje) Nie podano opisu zmian |
||
Linia 5:
Rozważmy, co się stanie, gdy zdefiniujemy metodę na samym szczycie hierarchii, nie wewnątrz jakiejkolwiek klasy? Możemy myśleć o takiej metodzie analogicznie jak o funkcji w bardziej tradycyjnym języku, takim jak C.
<source lang="ruby">
</source>
Wydaje się, że nasza nowa metoda nie należy do żadnej klasy, ale w rzeczywistości Ruby dodał ją do klasy <tt>Object</tt> która jest nadklasą każdej innej klasy. W rezultacie każdy obiekt powinien mieć możliwość używania tej metody. Jest to prawdą, ale z małym kruczkiem: jest to ''prywatna'' metoda każdej klasy. Wprawdzie będziemy jeszcze dokładnie rozważać co to znaczy, ale zauważmy, że jedną z konsekwencji tego faktu jest to, że metoda ta może być wywołana tylko w funkcyjnym stylu, jak poniżej:
<source lang="ruby">
</source>
Wyraźnie nie możemy wywołać metody na rzecz obiektu:
<source lang="ruby">
ERR: (eval):1: private method `kwadrat' called for "ryba":String
</
To raczej zręcznie chroni czysto obiektową naturę Rubiego (funkcje są wciąż metodami obiektów, ale odbiorcą domyślnie jest <tt>self</tt>) dostarczając funkcji które mogą być zapisane podobnie jak w bardziej tradycyjnym języku.
Linia 38 ⟶ 36:
Powszechną dyscypliną umysłową w programowaniu obiektowym, którą zasugerowaliśmy we wcześniejszym rozdziale, jest problem rozdzielenia ''specyfikacji'' i ''implementacji'', czyli ''jakie'' zadania wymagamy by obiekt wypełniał i ''jak'' je właściwie wypełnia. Wewnętrzne prace obiektu powinny być zazwyczaj ukryte przed jego użytkownikami. Powinni oni dbać o to, co wchodzi i wychodzi do/z obiektu oraz ufać, że obiekt wie co robi wewnętrznie z danymi. Z tego powodu często pomocne jest, gdy klasa posiada metody niewidoczne z zewnątrz, ale używane wewnętrznie, które mogą być poprawione przez programistę kiedy tylko zajdzie taka potrzeba, bez zmieniania sposobu, w jaki użytkownicy widzą obiekty danej klasy. W trywialnym przykładzie poniżej, pomyśl o metodzie <tt>wylicz</tt> jako o niewidocznych pracach klasy.
<source lang="ruby">
def
end end
test =
<source>
ruby> test.wylicz(6)▼
<source lang="ruby">
ERR: (eval):1: private method `wylicz' called for #<Test:0x4017181c>
</source>
ruby> test.dwa_razy(6)▼
6 razy dwa to 12▼
<source lang="ruby">
▲#=> 6 razy dwa to 12
</source>
Moglibyśmy oczekiwać, że <tt>test.wylicz(6)</tt> zwróci <tt>12</tt>, ale zamiast tego nauczyliśmy się, że metoda <tt>wylicz</tt> jest
== Modyfikatory dostępu ==
W Rubim mamy dostępne trzy modyfikatory dostępu.
{| class="wikitable"
! Modyfikator
! Działanie
|-
| <tt>private</tt>
| Metoda dostępna tylko dla obiektu danej klasy. Każdy obiekt danej klasy może wywoływać metody prywatne tylko na rzecz samego siebie. W innych językach programowania (np. w Javie) można wykonywać obiekty tej samej klasy mogą wykonywać swoje metody prywatne.
|-
| <tt>protected</tt>
| Metoda dostępna dla wszystkich obiektów danej klasy i klas potomnych.
|-
| <tt>public</tt>
| Metoda dostępna dla wszystkich obiektów.
|}
▲Moglibyśmy oczekiwać, że <tt>test.wylicz(6)</tt> zwróci <tt>12</tt>, ale zamiast tego nauczyliśmy się, że <tt>wylicz</tt> jest niedostępny, gdy odgrywamy rolę użytkownika obiektu <tt>Test</tt>. Tylko inne metody klasy <tt>Test</tt>, takie jak <tt>dwa_razy</tt> mogą korzystać z <tt>wylicz</tt>. Od nas wymagane jest posługiwanie się publicznym interfejsem, który składa się z metody <tt>dwa_razy</tt>. Programista, który jest pod kontrolą tej klasy może swobodnie modyfikować <tt>wylicz</tt> (tutaj, być może zmieniając <tt>b*2</tt> na <tt>b+b</tt> i argumentując to przypuszczalnie wzrostem wydajności) bez wpływania na to jak użytkownik współdziała z obiektami klasy <tt>Test</tt>. Ten przykład jest oczywiście zbyt prosty by był użyteczny; korzyści z metod kontroli dostępu staną się bardziej widoczne tylko wtedy, gdy zaczniemy tworzyć bardziej skomplikowane i interesujące klasy.
Dodatkowo warto zwrócić uwagę na oznaczanie nazw metod jako ''symboli'' (nazwa poprzedzona dwukropkiem) po modyfikatorze <tt>private</tt>. Gdybyśmy chcieli ukryć obie metody klasy <tt>Test2</tt> kod wyglądałby następująco:
|