Ruby/Akcesory
Akcesory
edytujCzym jest akcesor?
edytujKrótko omówiliśmy zmienne instancji we wcześniejszym rozdziale, ale jeszcze za wiele z nimi nie robiliśmy. Zmienne instancji obiektu są jego atrybutami, to te rzeczy, które odróżniają obiekt od innych obiektów tej samej klasy. Za ważną czynność zapisywania i odczytywania atrybutów odpowiedzialne są metody nazywane akcesorami atrybutów. Jak za chwilę zobaczymy, nie musimy pisać akcesorów bezpośrednio. Wcześniej jednak poznajmy wszystkie etapy ich tworzenia.
Wyróżniamy dwa rodzaje akcesorów: piszące (ang. writer[1]) i czytające (ang. reader[2]).
class Owoc
def zapisz_rodzaj(r) # akcesor piszacy
@rodzaj = r
end
def czytaj_rodzaj # akcesor czytajacy
@rodzaj
end
end
o1 = Owoc.new
# uzycie akcesora piszacego:
o1.zapisz_rodzaj("brzoskwinia")
# uzycie akcesora czytajacego:
o1.czytaj_rodzaj #=> "brzoskwinia"
Gdybyśmy wpisali powyższy kod do irba, moglibyśmy zastosować następujący sposób inspekcji:
irb(main):011:0> o1 => #<Owoc:0x2e47044 @rodzaj="brzoskwinia">
Proste prawda? Możemy przechowywać i odczytywać informację o tym, na jaki owoc patrzymy. Ale nasze nazwy metod są nieco rozwlekłe. W następującym przykładzie są już nieco bardziej zwięzłe i konwencjonalne:
class Owoc
def rodzaj=(r)
@rodzaj = r
end
def rodzaj
@rodzaj
end
end
o2 = Owoc.new
o2.rodzaj = "banan"
o2.rodzaj #=> "banan"
Metoda inspect
edytujJest tu potrzebna krótka dygresja. Z pewnością zauważyłeś, że jeżeli próbujemy spojrzeć na obiekt w irbie bezpośrednio, pokazuje się nam coś zagadkowego w rodzaju #<jakisObiekt:0x83678>. To jest po prostu domyślne zachowanie i oczywiście możemy je zmienić. Wszystko, co musimy zrobić to dodać metodę o nazwie inspect. Powinna ona zwracać łańcuch, który opisuje obiekt w jakiś sensowny sposób, włączając stany części lub wszystkich jego zmiennych instancji.
class Owoc
def inspect
"owoc rodzaju: #{@rodzaj}"
end
end
Podobną metodą jest metoda to_s (ang. convert to string - zamień na łańcuch), która jest używana gdy drukujemy obiekt. Ogólnie rzecz biorąc, możesz traktować inspect jako narzędzie, gdy piszesz i debugujesz programy, natomiast to_s jako sposób na formowanie wyjścia programu. irb używa inspect ilekroć wyświetla wyniki. Możesz użyć metody p by łatwo debugować wyjście z programów.
# Te dwie linie są równoważne:
p obiekt
puts obiekt.inspect
Łatwy sposób tworzenia akcesorów
edytujPonieważ wiele zmiennych instancji potrzebuje akcesorów, Ruby dostarcza wygodne skróty dla standardowych form.
Skrót | Efekt |
---|---|
attr_reader :v | def v; @v; end |
attr_writer :v | def v=(value); @v=value; end |
attr_accessor :v | attr_reader :v; attr_writer :v |
attr_accessor :v, :w | attr_accessor :v; attr_accessor :w |
Korzystając z tabeli uporządkujmy naszą klasę i dodajmy informację na temat świeżości. Najpierw automatycznie wygenerujemy akcesory: czytające i piszące, a następnie dodamy nową informację do metody inspect:
class Owoc
attr_accessor :stan
attr_accessor :gatunek
def inspect
"#{@stan} owoc rodzaju: #{@gatunek}"
end
end
o = Owoc.new
o.gatunek = "banan"
o.stan = "dojrzaly"
p o #=> dojrzaly owoc rodzaju: banan
Więcej zabawy z owocem
edytujJeżeli nikt nie zjadł naszego dojrzałego owocu, może należałoby pozwolić, by czas zebrał swoje żniwo (poniższy kod możemy dopisać bezpośrednio do powyższego):
class Owoc
def uplywa_czas
@stan = "gnijacy"
end
end
p o #=> dojrzaly owoc rodzaju: banan
o.uplywa_czas
p o #=> gnijacy owoc rodzaju: banan
W następnym rozdziale zobaczymy, jak zapewnić, by już w momencie utworzenia Owoc miał zdefiniowany rodzaj i stan.