Ruby ma wygodny i wygodny sposób udostępniania zmiennych instancji za pomocą kluczy podobnych do
attr_accessor :var
attr_reader :var
attr_writer :var
Dlaczego miałbym wybrać, attr_reader
czy attr_writer
mógłbym po prostu użyć attr_accessor
? Czy istnieje coś takiego jak wydajność (w co wątpię)? Sądzę, że jest ku temu powód, inaczej nie zrobiliby takich kluczy.
Odpowiedzi:
Możesz użyć różnych akcesoriów, aby przekazać swoją intencję komuś, kto czyta Twój kod, i ułatwić pisanie klas, które będą działać poprawnie bez względu na to, jak wywoływany jest ich publiczny interfejs API.
Widzę tutaj, że mogę zarówno czytać, jak i pisać wiek.
Widzę tutaj, że mogę tylko odczytać wiek. Wyobraź sobie, że jest ustawiony przez konstruktora tej klasy, a potem pozostaje stały. Gdyby istniał mutator (pisarz) dla wieku, a klasa została napisana przy założeniu, że ustawiony wiek nie zmienia się, wówczas błąd mógłby wynikać z wywołania kodu przez tego mutatora.
Ale co dzieje się za kulisami?
Jeśli napiszesz:
To przekłada się na:
Jeśli napiszesz:
To przekłada się na:
Jeśli napiszesz:
To przekłada się na:
Wiedząc o tym, oto inny sposób, aby o tym pomyśleć: jeśli nie miałbyś pomocników ATTR _... i musiałbyś sam napisać akcesory, czy napisałbyś więcej akcesorów niż potrzebna jest klasa? Na przykład, jeśli wiek należy tylko odczytać, czy napisałbyś również metodę pozwalającą na jego zapisanie?
źródło
attr_reader :a
kontradef a; return a; end
confreaks.net/videos/…attr_reader
zdefiniowany moduł dostępu zajmuje 86% czasu, co robi ręcznie zdefiniowany moduł dostępu. W przypadku Ruby 1.9.0attr_reader
zdefiniowany moduł dostępu zajmuje 94% czasu niż ręcznie zdefiniowany moduł dostępu . Jednak we wszystkich moich testach akcesoria są szybkie: akcesorium zajmuje około 820 nanosekund (Ruby 1.8.7) lub 440 nanosekund (Ruby 1.9). Przy tych prędkościach musisz zadzwonić do akcesorium setki milionów razy,attr_accessor
aby zwiększyć wydajność i poprawić ogólny czas działania nawet o jedną sekundę.attr_accessor :a, :b
Wszystkie powyższe odpowiedzi są poprawne;
attr_reader
iattr_writer
są wygodniejsze w pisaniu niż ręczne pisanie metod, dla których są skrótami. Poza tym oferują znacznie lepszą wydajność niż samodzielne pisanie definicji metody. Aby uzyskać więcej informacji, zobacz slajd 152 i następne z tej rozmowy ( PDF ) Aarona Pattersona.źródło
Nie wszystkie atrybuty obiektu powinny być ustawiane bezpośrednio spoza klasy. Posiadanie programów piszących dla wszystkich zmiennych instancji jest zazwyczaj oznaką słabego enkapsulacji i ostrzeżeniem, że wprowadzasz zbyt wiele sprzężeń między klasami.
Jako praktyczny przykład: napisałem program do projektowania, w którym wkładasz przedmioty do pojemników. Element miał
attr_reader :container
, ale nie miał sensu oferować pisarza, ponieważ pojemnik na przedmiot powinien zmienić się tylko wtedy, gdy zostanie umieszczony w nowym, co również wymaga informacji o położeniu.źródło
Ważne jest, aby zrozumieć, że akcesory ograniczają dostęp do zmiennych, ale nie ich treści. W Rubim, podobnie jak w niektórych innych językach OO, każda zmienna jest wskaźnikiem do instancji. Jeśli więc masz na przykład atrybut skrótu i ustawisz go jako „tylko do odczytu”, zawsze możesz zmienić jego zawartość, ale nie zawartość wskaźnika. Spójrz na to:
Jak widać, możliwe jest usunięcie pary klucz / wartość z Hash @a, ponieważ dodaj nowe klucze, zmień wartości, eccetera. Ale nie możesz wskazać nowego obiektu, ponieważ jest to zmienna instancji tylko do odczytu.
źródło
Nie zawsze chcesz, aby zmienne instancji były w pełni dostępne spoza klasy. Istnieje wiele przypadków, w których zezwala się na dostęp do odczytu do zmiennej instancji, ale zapis do niej może nie być (np. Model, który pobiera dane ze źródła tylko do odczytu). Są przypadki, w których chcesz czegoś przeciwnego, ale nie mogę wymyślić żadnych, które nie są wymyślone z góry mojej głowy.
źródło