Używanie atrybutów z kodem Ruby

Spójrz na dowolne kod zorientowany obiektowo i wszystko to mniej więcej ma ten sam wzór. Utwórz obiekt, wywołaj niektóre metody dla tego obiektu i uzyskaj dostęp do atrybutów tego obiektu. Nie można wiele więcej zrobić z obiektem poza przekazaniem go jako parametru do metody innego obiektu. Ale chodzi tutaj o atrybuty.

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

Ruby nie czyni rozróżnienia między modułami pobierania i ustawiania atrybutów a normalnymi metodami. Ze względu na elastyczną składnię wywoływania metody Ruby nie trzeba wprowadzać rozróżnienia. Na przykład,

instagram viewer
imię osoby i imię osoby() są takie same, dzwonisz Nazwa metoda z zerowymi parametrami. Jeden wygląda jak wywołanie metody, a drugi jak atrybut, ale tak naprawdę oba są tym samym. Oboje tylko dzwonią Nazwa metoda. Podobnie, dowolna nazwa metody, która kończy się znakiem równości (=), może być użyta w przydziale. Wyrok person.name = "Alice" to tak naprawdę to samo person.name = (alicja), mimo że między nazwą atrybutu a znakiem równości jest spacja, nadal wywołuje ona tylko nazwa = metoda.

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 osób. Przechowuje nazwę w @Nazwa zmienna instancji, ale nazwa nie musi być taka sama. Pamiętaj, że w tych metodach nie ma nic specjalnego.

Od razu zauważysz, że jest to dużo pracy. Dużo pisania polega tylko na tym, że chcesz nazwać atrybut Nazwa który ma dostęp do @Nazwa zmienna instancji. Na szczęście Ruby udostępnia kilka wygodnych metod, które zdefiniują te metody.

Istnieją trzy metody w Moduł klasa, której można używać w deklaracjach klas. Pamiętaj, że Ruby nie czyni rozróżnienia między czasem wykonania a „czasem kompilacji”, a każdy kod w deklaracjach klas może nie tylko definiować metody, ale także metody wywoływania. Dzwonię do attr_reader, attr_writer i attr_accessor metody z kolei zdefiniują ustawiające i pobierające, które zdefiniowaliśmy w poprzedniej sekcji.

The attr_reader metoda podoba się tak, jak się wydaje. Pobiera dowolną liczbę parametrów symboli i dla każdego parametru definiuje metodę „getter”, która zwraca zmienną instancji o tej samej nazwie. Możemy więc wymienić nasz Nazwa metoda w poprzednim przykładzie z attr_reader: nazwa.

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

I zgodnie z oczekiwaniami attr_accessor spełnia rolę obu attr_writer i attr_reader. Jeśli potrzebujesz atrybutu ustawiającego i pobierającego dla atrybutu, powszechną praktyką jest nie wywoływanie obu metod osobno, a zamiast tego wywoływanie attr_accessor. Możemy zastąpić obie Nazwa i nazwa = metody z poprzedniego przykładu za pomocą jednego wywołania do attr_accessor: name.

Dlaczego powinieneś definiować seterów ręcznie? Dlaczego nie skorzystać z attr_ * metody za każdym razem? Ponieważ łamią enkapsulację. Hermetyzacja jest zasadą, która stwierdza, że ​​żaden zewnętrzny podmiot nie powinien mieć nieograniczonego dostępu do wewnętrznego stanu twojego przedmioty. Dostęp do wszystkiego powinien odbywać się za pomocą interfejsu, który zapobiega uszkodzeniu przez użytkownika wewnętrznego stanu obiektu. Stosując powyższe metody, wybiliśmy dużą dziurę w ścianie enkapsulacji i pozwoliliśmy na ustawienie absolutnie wszystkiego dla nazwy, nawet oczywiście nieprawidłowej nazwy.

Często widzisz to attr_reader zostanie użyty do szybkiego zdefiniowania modułu pobierającego, ale zdefiniowany zostanie niestandardowy moduł ustawiający, ponieważ wewnętrzny stan obiektu często chce być czytać bezpośrednio ze stanu wewnętrznego. Seter jest następnie definiowany ręcznie i sprawdza, czy ustawiona wartość ma sens. Lub, być może częściej, żaden seter nie jest w ogóle definiowany. Inne metody w funkcji klasy ustawiają zmienną instancji za modułem pobierającym w inny sposób.

Możemy teraz dodać wiek i poprawnie wdrożyć Nazwa atrybut. The wiek atrybut można ustawić w metodzie konstruktora, odczyt za pomocą wiek getter, ale manipulowano tylko przy użyciu have_birthday metoda, która zwiększy wiek. The Nazwa atrybut ma normalny getter, ale ustawiający upewnia się, że nazwa jest pisana wielkimi literami i ma postać Imię Nazwisko.