Ruby/Kontrola dostępu
Z Wikibooks, biblioteki wolnych podręczników.
Spis treści |
[edytuj] Kontrola dostępu
Wcześniej powiedzieliśmy, że Ruby nie posiada funkcji, tylko metody. Jednakże jest nieco więcej różnych rodzajów metod. W tym rozdziale przedstawimy sposoby kontroli dostępu.
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.
def kwadrat(n) n * n end kwadrat(5) #=> 25
Wydaje się, że nasza nowa metoda nie należy do żadnej klasy, ale w rzeczywistości Ruby dodał ją do klasy Object 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:
class Klasa def czwarta_potega_z(x) kwadrat(x) * kwadrat(x) end end Klasa.new.czwarta_potega_z(10) #=> 10000
Wyraźnie nie możemy wywołać metody na rzecz obiektu:
"ryba".kwadrat(5) 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 self) dostarczając funkcji które mogą być zapisane podobnie jak w bardziej tradycyjnym języku.
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 wylicz jako o niewidocznych pracach klasy.
class Test def dwa_razy(a) puts "#{a} razy dwa to #{wylicz(a)}" end def wylicz(b) b*2 end private :wylicz # to ukryje wylicz przed uzytkownikami end test = Test.new test.wylicz(6) ERR: (eval):1: private method `wylicz' called for #<Test:0x4017181c>
test.dwa_razy(6) #=> 6 razy dwa to 12
Moglibyśmy oczekiwać, że test.wylicz(6) zwróci 12, ale zamiast tego nauczyliśmy się, że metoda wylicz jest niedostępna, gdy odgrywamy rolę użytkownika obiektu Test. Tylko inne metody klasy Test, takie jak dwa_razy mogą korzystać z wylicz. Od nas wymagane jest posługiwanie się publicznym interfejsem, który składa się z metody dwa_razy. Programista, który ma pod kontrolą tę klasę, może swobodnie modyfikować wylicz (tutaj, być może zmieniając b*2 na b+b i argumentując to przypuszczalnie wzrostem wydajności) bez wpływania na to jak użytkownik współdziała z obiektami klasy Test. 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.
[edytuj] Modyfikatory dostępu
W Rubim mamy dostępne trzy modyfikatory dostępu.
| Modyfikator | Tłumaczenie | Działanie |
|---|---|---|
| private | prywatny | 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) obiekty tej samej klasy mogą wykonywać swoje metody prywatne. |
| protected | chroniony | Metoda dostępna dla wszystkich obiektów danej klasy i klas potomnych. |
| public | publiczny | Metoda dostępna dla wszystkich obiektów. |
W Rubim modyfikatory dostępu dotyczą tylko metod. Jeżeli nie stosujemy żadnych modyfikatorów dostępu, domyślnym modyfikatorem jest public, tak więc wszystkie metody (poza initialize) są domyślnie publiczne. Dostęp do metod można określać na dwa sposoby:
- Stosując słowa kluczowe przed definicjami metod
- Stosując symbole o nazwach metod
[edytuj] Modyfikatory przed definicjami metod
class Test public # każda metoda (poza initialize, która jest prywatna) jest domyślnie publiczna def pub_met1 end def pub_met2 end private # metody prywatne def priv_met1 end protected # metody chronione def prot_met1 end def prot_met2 end end
Jak widzimy, modyfikatory dostępu (private, protected, public) występują tu przed definicjami metod.
[edytuj] Modyfikatory z symbolami
Identyczny efekt (z tym, że dostęp będzie nadawany dynamicznie) można uzyskać stosując modyfikatory oraz nazwy metod jako symbole. Co to są symbole powiemy dokładnie w rozdziale o symbolach.
class Test def pub_met1 end def pub_met2 end def priv_met1 end def prot_met1 end def prot_met2 end public :pub_met1, :pub_met2 private :priv_met1 protected :prot_met1, :prot_met2 end
Nazwy metod po modyfikatorach poprzedzone są dwukropkami (:) - tak właśnie oznaczamy symbole. Ale czym są owe symbole? Dowiedzmy się!