Co to jest attr_accessor w Ruby?


1023

Mam trudności ze zrozumieniem attr_accessorw języku Ruby .
Czy ktoś może mi to wyjaśnić?



1
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.

class Person
end

person = Person.new
person.name # => no method error

Oczywiście nigdy nie zdefiniowaliśmy metody name. Zróbmy to.

class Person
  def name
    @name # simply returning an instance variable @name
  end
end

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.

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

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.

class Person
  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!

class Person
  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.

class Person
  attr_accessor :name

  def greeting
    "Hello #{@name}"
  end
end

person = Person.new
person.name = "Dennis"
person.greeting # => "Hello Dennis"

Otóż ​​to. Aby zrozumieć, jak attr_reader, attr_writer, i attr_accessormetody faktycznie generuje metody, Przeczytaj inne odpowiedzi, książki, dokumenty Ruby.


46
@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:

  1. 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.

  2. 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:

class Foo
  attr_accessor :bar
end

jest równoważne z tym kodem:

class Foo
  def bar
    @bar
  end
  def bar=( new_value )
    @bar = new_value
  end
end

Możesz napisać tę metodę samodzielnie w Ruby:

class Module
  def 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
    end
  end
end

class Foo
  var :bar
end

f = Foo.new
p f.bar     #=> nil
f.bar = 42
p f.bar     #=> 42

3
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
end

def foo
  @foo
end

jest niczym więcej niż getter / setter dla obiektu


10
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.


4
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:

def self.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 setter
  end
end

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

class Person
  def name
    @name
  end

  def name=(str)
    @name = str
  end
end

person = Person.new
person.name = 'Eshaan'
person.name # => "Eshaan"

Metoda Settera

def name=(val)
  @name = val
end

Metoda Gettera

def name
  @name
end

Metoda Gettera i Settera w Rubim

class Person
  attr_accessor :name
end

person = Person.new
person.name = "Eshaan"
person.name # => "Eshaan"

2
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.

class Person

  def initialize(name)
    @name = name
  end


  def greeting
    "Hello #{@name}"
  end
end

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:

class Person
  attr_accessor :name

  # def initialize(name)
  #     @name = name
  # end

  def greeting
    "Hello #{name}"
  end
end

person = Person.new
person.name = "Dennis"
puts person.greeting

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.

class Item

  def initialize(item_name, quantity)
    @item_name = item_name
    @quantity = quantity
  end

  def item_name
    @item_name
  end

  def quantity
     @quantity
  end
end

example = Item.new("TV",2)
puts example.item_name
puts example.quantity

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;

class Item

attr_reader :item_name, :quantity

  def initialize(item_name, quantity)
    @item_name = item_name
    @quantity = quantity
  end

end

item = Item.new("TV",2)
puts item.item_name
puts item.quantity

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.

class Item

attr_reader :item_name

  def item_name=(str)
    @item_name = (str)
  end

end

Poniższy kod jest przykładem użycia attr_writer do ponownego skrócenia naszego kodu i zaoszczędzenia czasu.

class Item

attr_reader :item_name
attr_writer :item_name

end

item = Item.new
puts item.item_name = "TV"

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.

class Item

attr_reader :item_name

  def initialize(item_name)
    @item_name = item_name
  end

end

item = Item.new("TV")
puts item.item_name

attr_accessor: Wykonuje funkcje zarówno attr_reader, jak i attr_writer, oszczędzając ci jeszcze jedną linię kodu.


10

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:

class Person
end

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.


7

Po prostu zdefiniuje on ustawiającego i pobierającego dla klasy.

Zauważ, że

attr_reader :v is equivalant to 
def v
  @v
end

attr_writer :v is equivalant to
def v=(value)
  @v=value
end

Więc

attr_accessor :v which means 
attr_reader :v; attr_writer :v 

są równoważne w celu zdefiniowania settera i gettera dla klasy.


5

Po prostu attr-accessortworzy metody getteri setterdla określonych atrybutów


5

Innym sposobem na zrozumienie tego jest ustalenie, jaki kod błędu eliminuje poprzez posiadanie attr_accessor.

Przykład:

class BankAccount    
  def initialize( account_owner )
    @owner = account_owner
    @balance = 0
  end

  def deposit( amount )
    @balance = @balance + amount
  end

  def withdraw( amount )
    @balance = @balance - amount
  end
end

Dostępne są następujące metody:

$ bankie = BankAccout.new("Iggy")
$ bankie 
$ bankie.deposit(100)
$ bankie.withdraw(5)

Następujące metody generują błąd:

$ bankie.owner     #undefined method `owner'... 
$ bankie.balance   #undefined method `balance'...

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.

$ bankie.balance
$ bankie.owner

2

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.

module Mod
  attr_accessor(:one, :two)
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]

1

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


1

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.

class Foo
  attr_accessor 'myvar'
  def initialize
    @myvar = "A"
    myvar = "B"
    puts @myvar # A
    puts myvar # B - myvar declared above overrides myvar method
  end

  def 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 # C
  end
end

0

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.

class Car
  def initialize
    @wheels = 4  # This is an instance variable
  end
end

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.

class Car
  def wheels  # getter method
    @wheels
  end

  def wheels=(val)  # setter method
    @wheels = val
  end
end

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.

class Car
  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.


-2

Hmmm. Wiele dobrych odpowiedzi. Oto moje kilka centów na ten temat.

  • attr_accessorto 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.


-3

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!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.