Używanie atrybutów z Ruby

Spójrz na cokolwiekkod zorientowany obiektowoi wszystko mniej więcej według tego samego wzoru. Utwórz obiekt, wywołaj niektóre metody na tym obiekcie i uzyskaj dostęp do atrybutów tego obiektu. Niewiele więcej można zrobić z obiektem poza przekazaniem go jako parametru do metody innego obiektu. Ale to, czym zajmujemy się tutaj, to atrybuty.





Atrybuty są jak zmienne instancji możesz uzyskać dostęp za pomocą notacji kropkowej obiektu. Na przykład, imię osoby uzyska dostęp do nazwiska osoby. Podobnie często możesz przypisać do atrybutów takich jak person.name = 'Alicja' . Jest to funkcja podobna do zmiennych składowych (takich jak w C++), ale nie całkiem taka sama. Nie dzieje się tu nic specjalnego, atrybuty są implementowane w większości języków za pomocą „getterów” i „setterów” lub metod, które pobierają i ustawiają atrybuty ze zmiennych instancji.

Ruby nie rozróżnia między metodami pobierającymi i ustawiającymi atrybuty a normalnymi metodami. Ze względu na elastyczną składnię wywoływania metod Rubiego, nie trzeba dokonywać rozróżnienia. Na przykład, imię osoby oraz imię osoby() są tym samym, nazywasz to Nazwa metoda z zerowymi parametrami. Jeden wygląda jak wywołanie metody, a drugi wygląda jak atrybut, ale w rzeczywistości oba są tym samym. Oboje po prostu dzwonią Nazwa metoda. Podobnie w przypisaniu można użyć dowolnej nazwy metody, która kończy się znakiem równości (=). Wyrok person.name = 'Alicja' to naprawdę to samo, co person.name=(alicja) , mimo że między nazwą atrybutu a znakiem równości jest spacja, nadal wywołuje on tylko znak nazwa= metoda.



01 z 03

Samodzielne wdrażanie atrybutów

Zbliżenie kobiety

Andreas Larsson/Folio Images/Getty Images

Możesz łatwo samodzielnie zaimplementować atrybuty. Definiując metody ustawiające i pobierające, możesz zaimplementować dowolny atrybut. Oto przykładowy kod implementujący Nazwa atrybut dla klasy osoby. Przechowuje nazwę w @Nazwa zmienna instancji, ale nazwa nie musi być taka sama. Pamiętaj, nie ma nic specjalnego w tych metodach.



|_+_|

Jedną rzeczą, którą od razu zauważysz, jest to, że jest to dużo pracy. Dużo jest wpisywania tylko po to, by powiedzieć, że chcesz atrybut o nazwie Nazwa który uzyskuje dostęp do @Nazwa zmienna instancji. Na szczęście Ruby zapewnia kilka wygodnych metod, które zdefiniują te metody za Ciebie.

02 z 03

Korzystanie z attr_reader, attr_writer i attr_accessor

Istnieją trzy metody w Moduł klasy, której możesz użyć w swoich deklaracjach klas. Pamiętaj, że Ruby nie rozróżnia pomiędzy czasem wykonania a „czasem kompilacji”, a każdy kod wewnątrz deklaracji klas może nie tylko definiować metody, ale także wywoływać metody. Dzwonię do attr_reader, attr_writer i attr_accessor Metody z kolei zdefiniują settery i gettery, które sami zdefiniowaliśmy w poprzedniej sekcji.

The attr_reader Metoda działa dokładnie tak, jak wygląda na to, że zrobi. Pobiera dowolną liczbę parametrów symbolu i dla każdego parametru definiuje metodę pobierającą, która zwraca zmienną instancji o tej samej nazwie. Więc możemy zastąpić nasze Nazwa metoda w poprzednim przykładzie z attr_reader :nazwa .

Podobnie attr_writer Metoda definiuje metodę ustawiającą dla każdego przekazanego do niego symbolu. Zauważ, że znak równości nie musi być częścią symbolu, a jedynie nazwą atrybutu. Możemy wymienić nazwa= metoda z poprzedniego przykładu z wywołaniem do attr_writier :nazwa .



I zgodnie z oczekiwaniami attr_accessor wykonuje pracę obu attr_writer oraz attr_reader . Jeśli potrzebujesz zarówno settera, jak i gettera dla atrybutu, powszechną praktyką jest nie wywoływanie tych dwóch metod oddzielnie, a zamiast tego wywoływanie attr_accessor . Moglibyśmy wymienić Zarówno ten Nazwa oraz nazwa= metody z poprzedniego przykładu z pojedynczym wywołaniem do attr_accessor :nazwa .

|_+_| 03 z 03

Dlaczego warto ręcznie definiować setery i gettery?

Dlaczego należy definiować ustawiacze ręcznie? Dlaczego nie użyć atr_* metody za każdym razem? Ponieważ łamią hermetyzację. Enkapsulacja to zasada, która stwierdza, że ​​żaden podmiot zewnętrzny nie powinien mieć nieograniczonego dostępu do wewnętrznego stanu twojego przedmioty . Wszystko powinno być dostępne za pomocą interfejsu, który zapobiega uszkodzeniu wewnętrznego stanu obiektu przez użytkownika. Używając powyższych metod, wybiliśmy dużą dziurę w naszej ścianie enkapsulacji i pozwoliliśmy na ustawienie absolutnie wszystkiego dla nazwy, nawet oczywiście niepoprawnych nazw.



Jedną z rzeczy, które często widzisz, jest to attr_reader zostanie użyty do szybkiego zdefiniowania gettera, ale zostanie zdefiniowany niestandardowy setter, ponieważ wewnętrzny stan obiektu często chce być czytać bezpośrednio ze stanu wewnętrznego. Następnie ustawiający jest definiowany ręcznie i sprawdza, czy ustawiana wartość ma sens. Albo, być może częściej, nie ma w ogóle zdefiniowanego setera. Inne metody w funkcji klasy ustawiają zmienną instancji za getterem w inny sposób.

Możemy teraz dodać wiek i prawidłowo zaimplementować Nazwa atrybut. The wiek atrybut można ustawić w metodzie konstruktora, odczytać za pomocą wiek getter, ale manipulowany tylko za pomocą mieć_urodziny metoda, która zwiększy wiek. The Nazwa atrybut ma normalną metodę pobierania, ale ustawiacz zapewnia, że ​​nazwa jest pisana wielkimi literami i ma postać Imię Nazwisko .



|_+_|