Czy attr_accessor działa w ten sam sposób w Git? Uważam, że niektóre samouczki nie wyjaśniają wystarczająco, a inne zakładają wcześniejszą wiedzę.
Angelfirenze,
10
@Angelfirenze, gitnie ma z tym nic wspólnego attr_accessor. Git to oprogramowanie do kontroli wersji, podczas gdy attr_accessorjest metodą w Ruby .
Uzbekjon
Odpowiedzi:
2359
Powiedzmy, że masz klasę Person.
classPersonend
person =Person.new
person.name # => no method error
Oczywiście nigdy nie zdefiniowaliśmy metody name. Zróbmy to.
classPersondef name
@name# simply returning an instance variable @nameendend
person =Person.new
person.name # => nil
person.name ="Dennis"# => no method error
Aha, możemy odczytać imię, ale to nie znaczy, że możemy je przypisać. To są dwie różne metody. Ten pierwszy nazywa się czytelnikiem, a drugi pisarzem . Nie stworzyliśmy jeszcze pisarza, więc zróbmy to.
classPersondef name
@nameenddef name=(str)@name= str
endend
person =Person.new
person.name ='Dennis'
person.name # => "Dennis"
Niesamowite. Teraz możemy pisać i odczytywać zmienne instancji @nameza pomocą metod czytnika i zapisu . Tyle że dzieje się to tak często, dlaczego marnować czas na pisanie tych metod za każdym razem? Możemy to zrobić łatwiej.
classPerson
attr_reader :name
attr_writer :name
end
Nawet to może stać się powtarzalne. Jeśli chcesz zarówno czytnika, jak i pisarza, użyj akcesorium!
classPerson
attr_accessor :name
end
person =Person.new
person.name ="Dennis"
person.name # => "Dennis"
Działa w ten sam sposób! I zgadnij co: zmienna instancji @namew naszym obiekcie osoby zostanie ustawiona tak samo jak wtedy, gdy zrobiliśmy to ręcznie, więc możesz użyć jej w innych metodach.
Otóż to. Aby zrozumieć, jak attr_reader, attr_writer, i attr_accessormetody faktycznie generuje metody, Przeczytaj inne odpowiedzi, książki, dokumenty Ruby.
@hakunin - dziękuję za tę jasną odpowiedź. Czego mi brakuje, dlaczego składnia Rubiego sugeruje dwukropek „:” dla zmiennych instancji w instrukcji attr_ *? Wydaje się, że łatwiej byłoby zastosować tę samą składnię „@”, która jest używana w innym miejscu klasy w odniesieniu do zmiennej.
Czy
207
@WilliamSmith Aby odpowiedzieć na twoje pytanie, musisz zrozumieć, że attr_accessorjest to metoda wywoływana w bieżącej klasie i :nameparametr przekazywany do tej metody. To nie jest specjalna składnia, to proste wywołanie metody. Jeśli miałbyś nadać jej @namezmienną, nie miałoby to sensu, ponieważ @ nazwa zawierałaby nil. To byłoby jak pisanie attr_accessor nil. Nie przekazujesz jej zmiennej, którą musi utworzyć, przekazujesz nazwę, którą chcesz wywołać zmienną.
Max Chernyak
23
@hakunin - To ma sens. Właśnie dzisiaj dowiedziałem się, że ruby faktycznie „działa”, gdy analizuje plik, i że każda instrukcja i wyrażenie jest w rzeczywistości wywołaniem metody dla jakiegoś obiektu. W tym attr_accessor. Bardzo pomocny.
Czy
52
używałem Railsów przez 3 lata, nawet o tym nie wiedziałem. Wstyd
Sean Xiao
5
@Buminda tak, ale metoda namei zmienna @nameto nie to samo. Nie pomyl ich. W @nameswojej klasie masz zmienną instancji i określasz, że możesz attr_reader :nameją odczytać z zewnątrz. Bez tego attr_readernie ma prostego sposobu na uzyskanie dostępu @namepoza klasą.
Max Chernyak
127
attr_accessor to tylko metoda . (Link powinien zapewnić lepszy wgląd w to, jak to działa - spójrz na wygenerowane pary metod, a samouczek powinien pokazać, jak z niego korzystać.)
Sztuka polega na tym class nie jest to definicja w Rubim (jest to „tylko definicja” w językach takich jak C ++ i Java), ale jest to wyrażenie, które ocenia . To właśnie podczas tej oceny attr_accessorwywoływana jest metoda, która z kolei modyfikuje bieżącą klasę - pamiętaj niejawny odbiornik: self.attr_accessorgdzie selfjest w tym momencie obiekt klasy „otwartej”.
Potrzeba attr_accessori przyjaciele to:
Ruby, podobnie jak Smalltalk, nie pozwala na dostęp do zmiennych instancji poza metodami 1 dla tego obiektu. Oznacza to, że zmienne instancji nie mogą być dostępne w takiej x.yformie, jak to zwykle jest powiedziane, Java, a nawet Python. W Ruby yjest zawsze traktowany jako wiadomość do wysłania (lub „metoda wywołania”). W ten sposób attr_*metody tworzą opakowania, które zastępują @variabledostęp do instancji za pomocą dynamicznie tworzonych metod.
Kocioł jest do bani
Mam nadzieję, że to wyjaśnia niektóre małe szczegóły. Szczęśliwego kodowania.
1 Nie jest to do końca prawdą i istnieją wokół tego pewne „techniki” , ale nie ma obsługi składni dla dostępu do „zmiennej instancji publicznej”.
Kiedy mówisz, że attr_accessor jest „tylko metodą”, rozumiem to. Ale jaka jest składnia używana do wywoływania tej metody? Mam problem ze znalezieniem sekcji w dokumentacji ruby, która mówi o składni, takiej jak some_method: name => "okolwiek ",: notherName, itp.
BT
68
attr_accessorjest (jak stwierdzono @pst) tylko metodą. Tworzy dla ciebie więcej metod.
Więc ten kod tutaj:
classFoo
attr_accessor :bar
end
jest równoważne z tym kodem:
classFoodef bar
@barenddef bar=( new_value )@bar= new_value
endend
Możesz napisać tę metodę samodzielnie w Ruby:
classModuledef var( method_name )
inst_variable_name ="@#{method_name}".to_sym
define_method method_name do
instance_variable_get inst_variable_name
end
define_method "#{method_name}="do|new_value|
instance_variable_set inst_variable_name, new_value
endendendclassFoo
var :bar
end
f =Foo.new
p f.bar #=> nil
f.bar =42
p f.bar #=> 42
Jest to świetny przykład zastosowania metaprogramowania w nawet najbardziej początkujących scenariuszach. Bardzo dobrze.
John Simon
2
W końcu szukałem szkicu wdrożenia attr_accessori znalazłem tutaj! Chociaż rozwiązało to mój problem, ale jestem ciekawy, gdzie (książka / oficjalny dokument) mogę znaleźć taki przykład wdrożenia?
Wasif Hossain,
40
attr_accessor jest bardzo proste:
attr_accessor :foo
jest skrótem do:
def foo=(val)@foo= val
enddef foo
@fooend
jest niczym więcej niż getter / setter dla obiektu
twoja odpowiedź jest w porządku. „Skrót” oznacza „krótszą alternatywną trasę” według mojego słownika, a nie „cukier składniowy” lub „makro interpretowane przez tłumacza”.
bowsersenior
25
Zasadniczo fałszują publicznie dostępne atrybuty danych, których Ruby nie ma.
Chociaż ten komentarz nie jest całkowicie przydatny, to prawda. Podkreśla fakt, że publiczne atrybuty danych nie istnieją poza metodami „get” w Rubim, co jest naprawdę przydatną informacją dla kogoś, kto próbuje nauczyć się języka.
Eric Dand,
3
To naprawdę nie powinno być lekceważone. Jako nie-Rubinowy facet, który próbuje to rozgryźć, ta odpowiedź jest bardzo pomocna!
Brad
1
Zgoda, wydaje się bardzo podobna do nazwy C # {get; set;}
David Miler,
17
Jest to tylko metoda definiująca metody pobierające i ustawiające dla przykładowych zmiennych. Przykładową implementacją byłoby:
defself.attr_accessor(*names)
names.each do|name|
define_method(name){instance_variable_get("@#{name}")}# This is the getter
define_method("#{name}="){|arg| instance_variable_set("@#{name}", arg)}# This is the setterendend
obsługa wielu atrybutów w ten sposób jest świetna!
Wasif Hossain,
To był bardzo pomocny fragment kodu, który rozwiązał inne pytanie, które miałem związane z metaprogramowaniem.
alexventuraio
15
Proste objaśnienie bez żadnego kodu
Większość powyższych odpowiedzi używa kodu. To wyjaśnienie próbuje odpowiedzieć na to pytanie bez użycia jakiejkolwiek analogii / historii:
Strony zewnętrzne nie mają dostępu do wewnętrznych tajemnic CIA
Wyobraźmy sobie naprawdę tajne miejsce: CIA. Nikt nie wie, co dzieje się w CIA, poza ludźmi wewnątrz CIA. Innymi słowy, osoby zewnętrzne nie mogą uzyskać dostępu do żadnych informacji w CIA. Ale ponieważ nie jest dobrze mieć całkowicie tajną organizację, pewne informacje są udostępniane światu zewnętrznemu - tylko rzeczy, o których CIA chce oczywiście wiedzieć wszyscy: np. Dyrektor CIA, jak przyjazny dla środowiska ten departament jest porównywany do wszystkich innych departamentów rządowych itp. Inne informacje: np. kim są tajni agenci w Iraku lub Afganistanie - tego rodzaju rzeczy prawdopodobnie pozostaną tajemnicą przez następne 150 lat.
Jeśli jesteś poza CIA, możesz uzyskać dostęp tylko do informacji, które udostępniła publicznie. Lub, aby użyć języka CIA, możesz uzyskać dostęp tylko do informacji „wyczyszczonych”.
Informacje, które CIA chce udostępnić ogółowi społeczeństwa poza CIA, nazywane są: atrybutami.
Znaczenie atrybutów odczytu i zapisu:
W przypadku CIA większość atrybutów to „tylko do odczytu”. Oznacza to, że jeśli jesteś stroną spoza CIA, możesz zapytać: „kto jest dyrektorem CIA?” a otrzymasz prostą odpowiedź. Ale nie możesz zrobić z atrybutami „tylko do odczytu”, aby wprowadzić zmiany w CIA. np. nie możesz zadzwonić i nagle zdecydować , że chcesz, aby Kim Kardashian został dyrektorem, lub że chcesz, żeby Paris Hilton była naczelnym dowódcą.
Jeśli atrybuty dały ci dostęp do „zapisu”, możesz wprowadzić zmiany, jeśli chcesz, nawet jeśli jesteś na zewnątrz. W przeciwnym razie jedyne, co możesz zrobić, to przeczytać.
Innymi słowy, akcesory pozwalają zadawać zapytania lub wprowadzać zmiany w organizacjach, które w przeciwnym razie nie wpuszczają osób zewnętrznych, w zależności od tego, czy są to czytniki, czy zapisujące.
Przedmioty w klasie mogą mieć do siebie łatwy dostęp
Z drugiej strony, jeśli byłeś już w CIA, możesz łatwo wezwać swojego agenta CIA w Kabulu, ponieważ ta informacja jest łatwo dostępna , pod warunkiem, że jesteś już w środku. Ale jeśli jesteś poza CIA, po prostu nie otrzymasz dostępu: nie będziesz mógł wiedzieć, kim oni są (dostęp do odczytu), i nie będziesz mógł zmienić ich misji (dostęp do zapisu).
Dokładnie to samo z klasami i twoją możliwością dostępu do zmiennych, właściwości i metod w nich zawartych. HTH! Wszelkie pytania proszę zadawać i mam nadzieję, że wyjaśnię.
Twoje wyjaśnienie ma sens! +1 Przykro nam, czy jesteś pewien, że wyrażenie „informacja, która została wyczyszczona przez CIA, jest poprawne?
kouty,
w CIA istnieją różne poziomy „odprawy”: np. Ściśle tajne (nikt poza Prezem) lub zaufanie publiczne (każdy może przeczytać tę informację). CIA faktycznie dostarcza wielu bardzo fajnych faktów!
BKSpurgeon,
Zasługujesz na uznanie tylko dla przykładów Kardashian, Paris Hilton :) Pomyślałem, że było wystarczająco źle z Trumpem na prezydenta, wyobraź sobie tych dwóch odpowiedzialnych omg!
rmcsharry
Tak! Właśnie tego potrzebujemy, StackOverflow bez kodu! :-)
Marvin
13
Jeśli znasz koncepcję OOP, musisz zapoznać się z metodą getter i setter. attr_accessor robi to samo w Ruby.
Getter and Setter w ogólności
classPersondef name
@nameenddef name=(str)@name= str
endend
person =Person.new
person.name ='Eshaan'
person.name # => "Eshaan"
Metoda Settera
def name=(val)@name= val
end
Metoda Gettera
def name
@nameend
Metoda Gettera i Settera w Rubim
classPerson
attr_accessor :name
end
person =Person.new
person.name ="Eshaan"
person.name # => "Eshaan"
doskonałe wyjaśnienie! Jest to bardzo przydatne zachowanie i może być zbyt łatwo zastąpione.
Rubyrider,
12
Ja również zmierzyłem się z tym problemem i napisałem dość długą odpowiedź na to pytanie. Istnieją już świetne odpowiedzi na ten temat, ale każdy, kto szuka dodatkowych wyjaśnień, mam nadzieję, że moja odpowiedź może pomóc
Zainicjuj metodę
Inicjalizacja pozwala ustawić dane dla instancji obiektu po utworzeniu instancji zamiast konieczności ustawiania ich w osobnej linii w kodzie za każdym razem, gdy tworzysz nową instancję klasy.
classPersondef initialize(name)@name= name
enddef greeting
"Hello #{@name}"endend
person =Person.new("Denis")
puts person.greeting
W powyższym kodzie ustawiamy nazwę „Denis” przy użyciu metody inicjalizacji, przekazując Dennisowi przez parametr w opcji Inicjuj. Gdybyśmy chcieli ustawić nazwę bez metody inicjalizacji, moglibyśmy to zrobić w następujący sposób:
W powyższym kodzie ustawiamy nazwę, wywołując metodę setter attr_accessor przy użyciu person.name, a nie ustawiając wartości przy inicjalizacji obiektu.
Obie „metody” wykonywania tej pracy, ale inicjalizacja oszczędzają nam czas i wiersze kodu.
To jest jedyne zadanie inicjalizacji. Nie można wywoływać inicjalizacji jako metody. Aby faktycznie uzyskać wartości obiektu instancji, musisz użyć metod pobierających i ustawiających (attr_reader (get), attr_writer (set) i attr_accessor (oba)). Zobacz poniżej więcej szczegółów na ich temat.
Getters, attr_reader: Celem gettera jest zwrócenie wartości określonej zmiennej instancji. Odwiedź poniższy przykładowy kod, aby uzyskać informacje na temat tego.
W powyższym kodzie wywołujesz metody „item_name” i „ilość” w przypadku elementu „example”. „Puts example.item_name” i „example.quantity” zwróci (lub „get”) wartość parametrów przekazanych do „example” i wyświetli je na ekranie.
Na szczęście w Ruby istnieje nieodłączna metoda, która pozwala nam napisać ten kod bardziej zwięźle; metoda attr_reader. Zobacz kod poniżej;
Ta składnia działa dokładnie w ten sam sposób, tyle że oszczędza nam sześć linii kodu. Wyobraź sobie, że miałeś jeszcze 5 stanów przypisywanych do klasy Przedmiotów? Kod szybko się wydłuży.
Setters, attr_writer: Na początku spotkałem się z metodami setter, ponieważ w moich oczach wydawało się, że pełnią one identyczną funkcję jak metoda inicjalizacji. Poniżej wyjaśniam różnicę na podstawie mojego zrozumienia;
Jak wspomniano wcześniej, metoda inicjalizacji umożliwia ustawienie wartości dla wystąpienia obiektu podczas tworzenia obiektu.
Ale co, jeśli chcesz ustawić wartości później, po utworzeniu instancji, lub zmienić je po ich zainicjowaniu? Byłby to scenariusz, w którym użyłbyś metody ustawiającej. TO JEST RÓŻNICA. Nie musisz „ustawiać” określonego stanu, kiedy początkowo używasz metody attr_writer.
Poniższy kod jest przykładem użycia metody setter do zadeklarowania wartości item_name dla tego wystąpienia klasy Item. Zauważ, że nadal używamy metody getter attr_reader, abyśmy mogli pobrać wartości i wydrukować je na ekranie, na wypadek, gdybyś chciał przetestować kod samodzielnie.
Poniższy kod jest powtórzeniem powyższego przykładu inicjalizacji, w którym za pomocą funkcji inicjalizacji ustawia się wartość obiektów item_name podczas tworzenia.
Myślę, że częścią tego, co myli nowych Rubyistów / programistów (takich jak ja), jest:
„Dlaczego nie mogę po prostu powiedzieć instancji, że ma dowolny atrybut (np. Nazwę) i nadać temu atrybutowi wartość za jednym zamachem?”
Trochę bardziej uogólniony, ale tak to dla mnie kliknęło:
Dany:
classPersonend
Nie zdefiniowaliśmy osoby jako czegoś, co może mieć imię lub inne atrybuty w tym zakresie.
Jeśli więc:
baby =Person.new
... i spróbuj nadać im nazwę ...
baby.name ="Ruth"
Otrzymujemy błąd , ponieważ w Rubyland klasa Person obiektu nie jest coś, co jest związane z lub zdolne do posiadania „name” ... jeszcze!
ALE możemy użyć dowolnej z podanych metod (patrz poprzednie odpowiedzi) jako sposobu na powiedzenie: „Instancja klasy Person ( baby) może teraz mieć atrybut o nazwie„ name ”, dlatego mamy nie tylko składniowy sposób uzyskiwania i ustawienie tej nazwy, ale ma to sens. ”
Znów trafiam w to pytanie z nieco innej i bardziej ogólnej perspektywy, ale mam nadzieję, że to pomoże następnej instancji klasy Osoba, która znajdzie drogę do tego wątku.
owneri balancenie są technicznie metodą , ale atrybutem. Klasa BankAccount nie ma def owneri def balance. Jeśli tak, możesz użyć dwóch poniższych poleceń. Ale tych dwóch metod nie ma. Możesz jednak uzyskać dostęp do atrybutów tak, jakbyś miał dostęp do metody za pośrednictwem attr_accessor!! Stąd słowoattr_accessor . Atrybut. Accessor. Uzyskuje dostęp do atrybutów tak, jakbyś miał dostęp do metody.
Dodanie attr_accessor :balance, :ownerpozwala na czytanie i pisanie balanceoraz owner„metodę”. Teraz możesz użyć 2 ostatnich metod.
Definiuje nazwany atrybut dla tego modułu, gdzie nazwa to symbol.id2name, tworząc zmienną instancji (@nazwa) i odpowiednią metodę dostępu, aby ją odczytać. Tworzy również metodę o nazwie name = w celu ustawienia atrybutu.
Jestem nowy w rubinach i musiałem po prostu poradzić sobie ze zrozumieniem następującej dziwności. W przyszłości może pomóc komuś innemu. Ostatecznie jest tak, jak wspomniano powyżej, gdzie 2 funkcje (def myvar, def myvar =) obie uzyskują niejawnie dostęp do @myvar, ale metody te można zastąpić deklaracjami lokalnymi.
classFoo
attr_accessor 'myvar'def initialize
@myvar="A"
myvar ="B"
puts @myvar# A
puts myvar # B - myvar declared above overrides myvar methodenddef test
puts @myvar# A
puts myvar # A - coming from myvar accessor
myvar ="C"# local myvar overrides accessor
puts @myvar# A
puts myvar # C
send "myvar=","E"# not running "myvar =", but instead calls setter for @myvar
puts @myvar# E
puts myvar # Cendend
Atrybuty są komponentami klasy, do których można uzyskać dostęp spoza obiektu. Są znane jako właściwości w wielu innych językach programowania. Ich wartości są dostępne za pomocą „notacji kropkowej”, jak w nazwie nazwa_obiektu. Nazwa_atrybutu. W przeciwieństwie do Pythona i kilku innych języków, Ruby nie pozwala na dostęp do zmiennych instancji bezpośrednio z zewnątrz obiektu.
classCardef initialize
@wheels=4# This is an instance variableendend
c =Car.new
c.wheels # Output: NoMethodError: undefined method `wheels' for #<Car:0x00000000d43500>
W powyższym przykładzie c jest instancją (obiektem) klasy Car. Próbowaliśmy bezskutecznie odczytać wartość zmiennej instancji koła z zewnątrz obiektu. Stało się tak, że Ruby próbowała wywołać metodę o nazwie koła w obiekcie c, ale taka metoda nie została zdefiniowana. Krótko mówiąc, nazwa_obiektu. Nazwa_atrybutu próbuje wywołać metodę o nazwie nazwa_atrybutu w obiekcie. Aby uzyskać dostęp do wartości zmiennej koła z zewnątrz, musimy zaimplementować metodę instancji o tej nazwie, która zwróci wartość tej zmiennej po wywołaniu. To się nazywa metoda akcesorium. W ogólnym kontekście programowania typowym sposobem uzyskania dostępu do zmiennej instancji spoza obiektu jest zaimplementowanie metod akcesorów, znanych również jako metody pobierające i ustawiające.
W poniższym przykładzie dodaliśmy metody getter i setter do klasy Car, aby uzyskać dostęp do zmiennej koła spoza obiektu. To nie jest „rubinowy sposób” definiowania getterów i seterów; służy jedynie zilustrowaniu działania metod pobierających i ustawiających.
classCardef wheels # getter method@wheelsenddef wheels=(val)# setter method@wheels= val
endend
f =Car.new
f.wheels =4# The setter method was invoked
f.wheels # The getter method was invoked# Output: => 4
Powyższy przykład działa i podobny kod jest powszechnie używany do tworzenia metod pobierających i ustawiających w innych językach. Ruby zapewnia jednak prostszy sposób: trzy wbudowane metody o nazwie attr_reader, attr_writer i attr_acessor. Metoda attr_reader sprawia, że zmienna instancji jest czytelna z zewnątrz, attr_writer umożliwia jej zapis, a attr_acessor czyni ją czytelną i zapisywalną.
Powyższy przykład można przepisać w ten sposób.
classCar
attr_accessor :wheels
end
f =Car.new
f.wheels =4
f.wheels # Output: => 4
W powyższym przykładzie atrybut koła będzie czytelny i zapisywalny z zewnątrz obiektu. Jeśli zamiast attr_accessor użyjemy attr_reader, będzie to tylko do odczytu. Gdybyśmy użyli attr_writer, byłoby to tylko do zapisu. Te trzy metody same w sobie nie są metodami pobierającymi i ustawiającymi, ale po wywołaniu tworzą dla nas metody pobierające i ustawiające. Są to metody, które dynamicznie (programowo) generują inne metody; to się nazywa metaprogramowanie.
Pierwszy (dłuższy) przykład, który nie wykorzystuje wbudowanych metod Ruby, powinien być używany tylko wtedy, gdy wymagany jest dodatkowy kod w metodach pobierających i ustawiających. Na przykład metoda ustawiająca może wymagać weryfikacji danych lub wykonania obliczeń przed przypisaniem wartości do zmiennej instancji.
Dostęp do zmiennych instancji (odczyt i zapis) można uzyskać z zewnątrz obiektu, korzystając z wbudowanych metod zestaw_instancji_wystąpienia i zestawu_instancji_wystąpienia. Jest to jednak rzadko uzasadnione i zwykle zły pomysł, ponieważ ominięcie enkapsulacji powoduje zwykle spustoszenie.
Główną funkcjonalnością attr_accessor nad pozostałymi jest możliwość dostępu do danych z innych plików.
Zwykle masz attr_reader lub attr_writer, ale dobrą wiadomością jest to, że Ruby pozwala łączyć te dwa elementy z attr_accessor. Myślę, że to moja metoda ponieważ jest bardziej zaokrąglona lub wszechstronna. Pamiętaj też, że w Railsach jest to eliminowane, ponieważ robi to za Ciebie w back-endie. Innymi słowy: lepiej jest użyć attr_acessor w porównaniu do pozostałych dwóch, ponieważ nie musisz się martwić, że jesteś konkretny, akcesorium to wszystko obejmuje. Wiem, że to bardziej ogólne wyjaśnienie, ale pomogło mi to jako początkującym.
git
nie ma z tym nic wspólnegoattr_accessor
. Git to oprogramowanie do kontroli wersji, podczas gdyattr_accessor
jest metodą w Ruby .Odpowiedzi:
Powiedzmy, że masz klasę
Person
.Oczywiście nigdy nie zdefiniowaliśmy metody
name
. Zróbmy to.Aha, możemy odczytać imię, ale to nie znaczy, że możemy je przypisać. To są dwie różne metody. Ten pierwszy nazywa się czytelnikiem, a drugi pisarzem . Nie stworzyliśmy jeszcze pisarza, więc zróbmy to.
Niesamowite. Teraz możemy pisać i odczytywać zmienne instancji
@name
za pomocą metod czytnika i zapisu . Tyle że dzieje się to tak często, dlaczego marnować czas na pisanie tych metod za każdym razem? Możemy to zrobić łatwiej.Nawet to może stać się powtarzalne. Jeśli chcesz zarówno czytnika, jak i pisarza, użyj akcesorium!
Działa w ten sam sposób! I zgadnij co: zmienna instancji
@name
w naszym obiekcie osoby zostanie ustawiona tak samo jak wtedy, gdy zrobiliśmy to ręcznie, więc możesz użyć jej w innych metodach.Otóż to. Aby zrozumieć, jak
attr_reader
,attr_writer
, iattr_accessor
metody faktycznie generuje metody, Przeczytaj inne odpowiedzi, książki, dokumenty Ruby.źródło
attr_accessor
jest to metoda wywoływana w bieżącej klasie i:name
parametr przekazywany do tej metody. To nie jest specjalna składnia, to proste wywołanie metody. Jeśli miałbyś nadać jej@name
zmienną, nie miałoby to sensu, ponieważ @ nazwa zawierałabynil
. To byłoby jak pisanieattr_accessor nil
. Nie przekazujesz jej zmiennej, którą musi utworzyć, przekazujesz nazwę, którą chcesz wywołać zmienną.name
i zmienna@name
to nie to samo. Nie pomyl ich. W@name
swojej klasie masz zmienną instancji i określasz, że możeszattr_reader :name
ją odczytać z zewnątrz. Bez tegoattr_reader
nie ma prostego sposobu na uzyskanie dostępu@name
poza klasą.attr_accessor to tylko metoda . (Link powinien zapewnić lepszy wgląd w to, jak to działa - spójrz na wygenerowane pary metod, a samouczek powinien pokazać, jak z niego korzystać.)
Sztuka polega na tym
class
nie jest to definicja w Rubim (jest to „tylko definicja” w językach takich jak C ++ i Java), ale jest to wyrażenie, które ocenia . To właśnie podczas tej ocenyattr_accessor
wywoływana jest metoda, która z kolei modyfikuje bieżącą klasę - pamiętaj niejawny odbiornik:self.attr_accessor
gdzieself
jest w tym momencie obiekt klasy „otwartej”.Potrzeba
attr_accessor
i przyjaciele to:Ruby, podobnie jak Smalltalk, nie pozwala na dostęp do zmiennych instancji poza metodami 1 dla tego obiektu. Oznacza to, że zmienne instancji nie mogą być dostępne w takiej
x.y
formie, jak to zwykle jest powiedziane, Java, a nawet Python. W Rubyy
jest zawsze traktowany jako wiadomość do wysłania (lub „metoda wywołania”). W ten sposóbattr_*
metody tworzą opakowania, które zastępują@variable
dostęp do instancji za pomocą dynamicznie tworzonych metod.Kocioł jest do bani
Mam nadzieję, że to wyjaśnia niektóre małe szczegóły. Szczęśliwego kodowania.
1 Nie jest to do końca prawdą i istnieją wokół tego pewne „techniki” , ale nie ma obsługi składni dla dostępu do „zmiennej instancji publicznej”.
źródło
attr_accessor
jest (jak stwierdzono @pst) tylko metodą. Tworzy dla ciebie więcej metod.Więc ten kod tutaj:
jest równoważne z tym kodem:
Możesz napisać tę metodę samodzielnie w Ruby:
źródło
attr_accessor
i znalazłem tutaj! Chociaż rozwiązało to mój problem, ale jestem ciekawy, gdzie (książka / oficjalny dokument) mogę znaleźć taki przykład wdrożenia?attr_accessor
jest bardzo proste:jest skrótem do:
jest niczym więcej niż getter / setter dla obiektu
źródło
Zasadniczo fałszują publicznie dostępne atrybuty danych, których Ruby nie ma.
źródło
Jest to tylko metoda definiująca metody pobierające i ustawiające dla przykładowych zmiennych. Przykładową implementacją byłoby:
źródło
Proste objaśnienie bez żadnego kodu
Większość powyższych odpowiedzi używa kodu. To wyjaśnienie próbuje odpowiedzieć na to pytanie bez użycia jakiejkolwiek analogii / historii:
Strony zewnętrzne nie mają dostępu do wewnętrznych tajemnic CIA
Wyobraźmy sobie naprawdę tajne miejsce: CIA. Nikt nie wie, co dzieje się w CIA, poza ludźmi wewnątrz CIA. Innymi słowy, osoby zewnętrzne nie mogą uzyskać dostępu do żadnych informacji w CIA. Ale ponieważ nie jest dobrze mieć całkowicie tajną organizację, pewne informacje są udostępniane światu zewnętrznemu - tylko rzeczy, o których CIA chce oczywiście wiedzieć wszyscy: np. Dyrektor CIA, jak przyjazny dla środowiska ten departament jest porównywany do wszystkich innych departamentów rządowych itp. Inne informacje: np. kim są tajni agenci w Iraku lub Afganistanie - tego rodzaju rzeczy prawdopodobnie pozostaną tajemnicą przez następne 150 lat.
Jeśli jesteś poza CIA, możesz uzyskać dostęp tylko do informacji, które udostępniła publicznie. Lub, aby użyć języka CIA, możesz uzyskać dostęp tylko do informacji „wyczyszczonych”.
Informacje, które CIA chce udostępnić ogółowi społeczeństwa poza CIA, nazywane są: atrybutami.
Znaczenie atrybutów odczytu i zapisu:
W przypadku CIA większość atrybutów to „tylko do odczytu”. Oznacza to, że jeśli jesteś stroną spoza CIA, możesz zapytać: „kto jest dyrektorem CIA?” a otrzymasz prostą odpowiedź. Ale nie możesz zrobić z atrybutami „tylko do odczytu”, aby wprowadzić zmiany w CIA. np. nie możesz zadzwonić i nagle zdecydować , że chcesz, aby Kim Kardashian został dyrektorem, lub że chcesz, żeby Paris Hilton była naczelnym dowódcą.
Jeśli atrybuty dały ci dostęp do „zapisu”, możesz wprowadzić zmiany, jeśli chcesz, nawet jeśli jesteś na zewnątrz. W przeciwnym razie jedyne, co możesz zrobić, to przeczytać.
Innymi słowy, akcesory pozwalają zadawać zapytania lub wprowadzać zmiany w organizacjach, które w przeciwnym razie nie wpuszczają osób zewnętrznych, w zależności od tego, czy są to czytniki, czy zapisujące.
Przedmioty w klasie mogą mieć do siebie łatwy dostęp
Dokładnie to samo z klasami i twoją możliwością dostępu do zmiennych, właściwości i metod w nich zawartych. HTH! Wszelkie pytania proszę zadawać i mam nadzieję, że wyjaśnię.
źródło
Jeśli znasz koncepcję OOP, musisz zapoznać się z metodą getter i setter. attr_accessor robi to samo w Ruby.
Getter and Setter w ogólności
Metoda Settera
Metoda Gettera
Metoda Gettera i Settera w Rubim
źródło
Ja również zmierzyłem się z tym problemem i napisałem dość długą odpowiedź na to pytanie. Istnieją już świetne odpowiedzi na ten temat, ale każdy, kto szuka dodatkowych wyjaśnień, mam nadzieję, że moja odpowiedź może pomóc
Zainicjuj metodę
Inicjalizacja pozwala ustawić dane dla instancji obiektu po utworzeniu instancji zamiast konieczności ustawiania ich w osobnej linii w kodzie za każdym razem, gdy tworzysz nową instancję klasy.
W powyższym kodzie ustawiamy nazwę „Denis” przy użyciu metody inicjalizacji, przekazując Dennisowi przez parametr w opcji Inicjuj. Gdybyśmy chcieli ustawić nazwę bez metody inicjalizacji, moglibyśmy to zrobić w następujący sposób:
W powyższym kodzie ustawiamy nazwę, wywołując metodę setter attr_accessor przy użyciu person.name, a nie ustawiając wartości przy inicjalizacji obiektu.
Obie „metody” wykonywania tej pracy, ale inicjalizacja oszczędzają nam czas i wiersze kodu.
To jest jedyne zadanie inicjalizacji. Nie można wywoływać inicjalizacji jako metody. Aby faktycznie uzyskać wartości obiektu instancji, musisz użyć metod pobierających i ustawiających (attr_reader (get), attr_writer (set) i attr_accessor (oba)). Zobacz poniżej więcej szczegółów na ich temat.
Getters, Setters (attr_reader, attr_writer, attr_accessor)
Getters, attr_reader: Celem gettera jest zwrócenie wartości określonej zmiennej instancji. Odwiedź poniższy przykładowy kod, aby uzyskać informacje na temat tego.
W powyższym kodzie wywołujesz metody „item_name” i „ilość” w przypadku elementu „example”. „Puts example.item_name” i „example.quantity” zwróci (lub „get”) wartość parametrów przekazanych do „example” i wyświetli je na ekranie.
Na szczęście w Ruby istnieje nieodłączna metoda, która pozwala nam napisać ten kod bardziej zwięźle; metoda attr_reader. Zobacz kod poniżej;
Ta składnia działa dokładnie w ten sam sposób, tyle że oszczędza nam sześć linii kodu. Wyobraź sobie, że miałeś jeszcze 5 stanów przypisywanych do klasy Przedmiotów? Kod szybko się wydłuży.
Setters, attr_writer: Na początku spotkałem się z metodami setter, ponieważ w moich oczach wydawało się, że pełnią one identyczną funkcję jak metoda inicjalizacji. Poniżej wyjaśniam różnicę na podstawie mojego zrozumienia;
Jak wspomniano wcześniej, metoda inicjalizacji umożliwia ustawienie wartości dla wystąpienia obiektu podczas tworzenia obiektu.
Ale co, jeśli chcesz ustawić wartości później, po utworzeniu instancji, lub zmienić je po ich zainicjowaniu? Byłby to scenariusz, w którym użyłbyś metody ustawiającej. TO JEST RÓŻNICA. Nie musisz „ustawiać” określonego stanu, kiedy początkowo używasz metody attr_writer.
Poniższy kod jest przykładem użycia metody setter do zadeklarowania wartości item_name dla tego wystąpienia klasy Item. Zauważ, że nadal używamy metody getter attr_reader, abyśmy mogli pobrać wartości i wydrukować je na ekranie, na wypadek, gdybyś chciał przetestować kod samodzielnie.
Poniższy kod jest przykładem użycia attr_writer do ponownego skrócenia naszego kodu i zaoszczędzenia czasu.
Poniższy kod jest powtórzeniem powyższego przykładu inicjalizacji, w którym za pomocą funkcji inicjalizacji ustawia się wartość obiektów item_name podczas tworzenia.
attr_accessor: Wykonuje funkcje zarówno attr_reader, jak i attr_writer, oszczędzając ci jeszcze jedną linię kodu.
źródło
Myślę, że częścią tego, co myli nowych Rubyistów / programistów (takich jak ja), jest:
„Dlaczego nie mogę po prostu powiedzieć instancji, że ma dowolny atrybut (np. Nazwę) i nadać temu atrybutowi wartość za jednym zamachem?”
Trochę bardziej uogólniony, ale tak to dla mnie kliknęło:
Dany:
Nie zdefiniowaliśmy osoby jako czegoś, co może mieć imię lub inne atrybuty w tym zakresie.
Jeśli więc:
... i spróbuj nadać im nazwę ...
Otrzymujemy błąd , ponieważ w Rubyland klasa Person obiektu nie jest coś, co jest związane z lub zdolne do posiadania „name” ... jeszcze!
ALE możemy użyć dowolnej z podanych metod (patrz poprzednie odpowiedzi) jako sposobu na powiedzenie: „Instancja klasy Person (
baby
) może teraz mieć atrybut o nazwie„ name ”, dlatego mamy nie tylko składniowy sposób uzyskiwania i ustawienie tej nazwy, ale ma to sens. ”Znów trafiam w to pytanie z nieco innej i bardziej ogólnej perspektywy, ale mam nadzieję, że to pomoże następnej instancji klasy Osoba, która znajdzie drogę do tego wątku.
źródło
Po prostu zdefiniuje on ustawiającego i pobierającego dla klasy.
Zauważ, że
Więc
są równoważne w celu zdefiniowania settera i gettera dla klasy.
źródło
Po prostu
attr-accessor
tworzy metodygetter
isetter
dla określonych atrybutówźródło
Innym sposobem na zrozumienie tego jest ustalenie, jaki kod błędu eliminuje poprzez posiadanie
attr_accessor
.Przykład:
Dostępne są następujące metody:
Następujące metody generują błąd:
owner
ibalance
nie są technicznie metodą , ale atrybutem. Klasa BankAccount nie madef owner
idef balance
. Jeśli tak, możesz użyć dwóch poniższych poleceń. Ale tych dwóch metod nie ma. Możesz jednak uzyskać dostęp do atrybutów tak, jakbyś miał dostęp do metody za pośrednictwemattr_accessor
!! Stąd słowoattr_accessor
. Atrybut. Accessor. Uzyskuje dostęp do atrybutów tak, jakbyś miał dostęp do metody.Dodanie
attr_accessor :balance, :owner
pozwala na czytanie i pisaniebalance
orazowner
„metodę”. Teraz możesz użyć 2 ostatnich metod.źródło
Definiuje nazwany atrybut dla tego modułu, gdzie nazwa to symbol.id2name, tworząc zmienną instancji (@nazwa) i odpowiednią metodę dostępu, aby ją odczytać. Tworzy również metodę o nazwie name = w celu ustawienia atrybutu.
źródło
Podsumowując atrybut accessor aka attr_accessor daje dwie bezpłatne metody.
Podobnie jak w Javie, nazywane są modułami pobierającymi i ustawiającymi.
Wiele odpowiedzi pokazało dobre przykłady, więc powiem krótko.
# atrybut
i
# the_attribute =
W starych dokumentach ruby hash tag # oznacza metodę. Może także zawierać prefiks nazwy klasy ... MyClass # my_method
źródło
Jestem nowy w rubinach i musiałem po prostu poradzić sobie ze zrozumieniem następującej dziwności. W przyszłości może pomóc komuś innemu. Ostatecznie jest tak, jak wspomniano powyżej, gdzie 2 funkcje (def myvar, def myvar =) obie uzyskują niejawnie dostęp do @myvar, ale metody te można zastąpić deklaracjami lokalnymi.
źródło
Atrybuty i metody akcesorów
Atrybuty są komponentami klasy, do których można uzyskać dostęp spoza obiektu. Są znane jako właściwości w wielu innych językach programowania. Ich wartości są dostępne za pomocą „notacji kropkowej”, jak w nazwie nazwa_obiektu. Nazwa_atrybutu. W przeciwieństwie do Pythona i kilku innych języków, Ruby nie pozwala na dostęp do zmiennych instancji bezpośrednio z zewnątrz obiektu.
W powyższym przykładzie c jest instancją (obiektem) klasy Car. Próbowaliśmy bezskutecznie odczytać wartość zmiennej instancji koła z zewnątrz obiektu. Stało się tak, że Ruby próbowała wywołać metodę o nazwie koła w obiekcie c, ale taka metoda nie została zdefiniowana. Krótko mówiąc, nazwa_obiektu. Nazwa_atrybutu próbuje wywołać metodę o nazwie nazwa_atrybutu w obiekcie. Aby uzyskać dostęp do wartości zmiennej koła z zewnątrz, musimy zaimplementować metodę instancji o tej nazwie, która zwróci wartość tej zmiennej po wywołaniu. To się nazywa metoda akcesorium. W ogólnym kontekście programowania typowym sposobem uzyskania dostępu do zmiennej instancji spoza obiektu jest zaimplementowanie metod akcesorów, znanych również jako metody pobierające i ustawiające.
W poniższym przykładzie dodaliśmy metody getter i setter do klasy Car, aby uzyskać dostęp do zmiennej koła spoza obiektu. To nie jest „rubinowy sposób” definiowania getterów i seterów; służy jedynie zilustrowaniu działania metod pobierających i ustawiających.
Powyższy przykład działa i podobny kod jest powszechnie używany do tworzenia metod pobierających i ustawiających w innych językach. Ruby zapewnia jednak prostszy sposób: trzy wbudowane metody o nazwie attr_reader, attr_writer i attr_acessor. Metoda attr_reader sprawia, że zmienna instancji jest czytelna z zewnątrz, attr_writer umożliwia jej zapis, a attr_acessor czyni ją czytelną i zapisywalną.
Powyższy przykład można przepisać w ten sposób.
W powyższym przykładzie atrybut koła będzie czytelny i zapisywalny z zewnątrz obiektu. Jeśli zamiast attr_accessor użyjemy attr_reader, będzie to tylko do odczytu. Gdybyśmy użyli attr_writer, byłoby to tylko do zapisu. Te trzy metody same w sobie nie są metodami pobierającymi i ustawiającymi, ale po wywołaniu tworzą dla nas metody pobierające i ustawiające. Są to metody, które dynamicznie (programowo) generują inne metody; to się nazywa metaprogramowanie.
Pierwszy (dłuższy) przykład, który nie wykorzystuje wbudowanych metod Ruby, powinien być używany tylko wtedy, gdy wymagany jest dodatkowy kod w metodach pobierających i ustawiających. Na przykład metoda ustawiająca może wymagać weryfikacji danych lub wykonania obliczeń przed przypisaniem wartości do zmiennej instancji.
Dostęp do zmiennych instancji (odczyt i zapis) można uzyskać z zewnątrz obiektu, korzystając z wbudowanych metod zestaw_instancji_wystąpienia i zestawu_instancji_wystąpienia. Jest to jednak rzadko uzasadnione i zwykle zły pomysł, ponieważ ominięcie enkapsulacji powoduje zwykle spustoszenie.
źródło
Hmmm. Wiele dobrych odpowiedzi. Oto moje kilka centów na ten temat.
attr_accessor
to prosta metoda, która pomaga nam w czyszczeniu ( osuszaniu ) powtarzaniagetter and setter
metod.Abyśmy mogli bardziej skoncentrować się na pisaniu logiki biznesowej i nie martwić się o ustawiających i pobierających.
źródło
Główną funkcjonalnością attr_accessor nad pozostałymi jest możliwość dostępu do danych z innych plików.
Zwykle masz attr_reader lub attr_writer, ale dobrą wiadomością jest to, że Ruby pozwala łączyć te dwa elementy z attr_accessor. Myślę, że to moja metoda ponieważ jest bardziej zaokrąglona lub wszechstronna. Pamiętaj też, że w Railsach jest to eliminowane, ponieważ robi to za Ciebie w back-endie. Innymi słowy: lepiej jest użyć attr_acessor w porównaniu do pozostałych dwóch, ponieważ nie musisz się martwić, że jesteś konkretny, akcesorium to wszystko obejmuje. Wiem, że to bardziej ogólne wyjaśnienie, ale pomogło mi to jako początkującym.
Mam nadzieję, że to pomogło!
źródło