Właściwości obliczane
Część sekcji Programowanie obiektowe ścieżki Lua w Coddy. Lekcja 15 z 70.
Gettery i settery zapewniają dostęp do przechowywanych wartości, ale czasami potrzebujesz danych, które nie istnieją jako przechowywane pole. Trzeba je obliczyć na podstawie innych atrybutów. Nazywa się je właściwościami obliczanymi.
Rozważ prostokąt. Zapisujesz jego szerokość i wysokość, ale pole nie jest nigdzie przechowywane: oblicza się je, mnożąc te dwie wartości. Zamiast przechowywać nadmiarowe dane, tworzysz metodę, która oblicza i zwraca wynik:
local Rectangle = {}
Rectangle.__index = Rectangle
function Rectangle:new(width, height)
local instance = {}
setmetatable(instance, self)
instance.width = width
instance.height = height
return instance
end
function Rectangle:getArea()
return self.width * self.height
endMetoda :getArea() nie zwraca zapisanej wartości. Oblicza pole od nowa za każdym razem, gdy ją wywołujesz. To podejście ma istotną zaletę: jeśli szerokość lub wysokość się zmieni, pole automatycznie uwzględni nowe wymiary, bez konieczności aktualizowania czegokolwiek.
local box = Rectangle:new(5, 3)
print(box:getArea()) -- Wynik: 15
box.width = 10
print(box:getArea()) -- Wynik: 30Właściwości obliczane pomagają zachować spójność obiektów. Zamiast przechowywać wartości zależne od innych pól (i ryzykować, że staną się nieaktualne), obliczasz je na żądanie. Ten wzorzec sprawdza się w przypadku wszelkich danych pochodnych: obwodów, średnich, sformatowanych ciągów znaków lub dowolnej wartości, którą można wyznaczyć na podstawie istniejących atrybutów.
Wyzwanie
ŁatwyZbudujmy klasę Box, która oblicza swoją objętość na żądanie! Zamiast przechowywać objętość jako pole, utworzysz obliczaną właściwość, która wylicza ją z wymiarów pudełka zawsze wtedy, gdy jest potrzebna.
Rozmieścisz swój kod w dwóch plikach:
Box.lua: Zdefiniuj klasęBoxprzy użyciu standardowego wzorca prototypowego. Każde pudełko przechowuje trzy wymiary:width,heightidepth. Uwzględnij:- Konstruktor
:new(width, height, depth), który przechowuje wszystkie trzy wymiary - Metodę
:getVolume(), która oblicza i zwraca objętość (width × height × depth) - Metodę
:getSurfaceArea(), która oblicza i zwraca całkowite pole powierzchni
- Konstruktor
main.lua: Załaduj swój moduł Box, utwórz instancję pudełka i pokaż, jak obliczane właściwości automatycznie uwzględniają aktualne wymiary.
Pole powierzchni pudełka oblicza się następująco: 2 × (width×height + height×depth + width×depth)
Otrzymasz trzy dane wejściowe reprezentujące wymiary pudełka:
- Szerokość
- Wysokość
- Głębokość
W pliku głównym utwórz pudełko o podanych wymiarach, a następnie wypisz dwa wiersze:
- Objętość za pomocą
:getVolume() - Pole powierzchni za pomocą
:getSurfaceArea()
Na przykład, jeśli dane wejściowe to 3, 4 i 5, wynik powinien wyglądać tak:
60
94Zaletą obliczanych właściwości jest to, że zawsze pozostają aktualne. Jeśli później zmienisz jeden z wymiarów pudełka, ponowne wywołanie :getVolume() automatycznie zwróci prawidłową nową wartość: nie trzeba niczego aktualizować ręcznie!
Spróbuj swoich sił
-- Załaduj moduł Box za pomocą require
local Box = require('Box')
-- Odczytaj wymiary wejściowe
local width = tonumber(io.read())
local height = tonumber(io.read())
local depth = tonumber(io.read())
-- TODO: Utwórz instancję pudełka o podanych wymiarach
-- TODO: Wypisz objętość za pomocą :getVolume()
-- TODO: Wypisz pole powierzchni za pomocą :getSurfaceArea()
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Koncepcja „self”
Tabele z funkcjamiJawne „self”Składnia z dwukropkiemKropka czy dwukropekPodsumowanie — poruszający się punkt4Projekt: Bank cyfrowy
Konfiguracja projektuMetoda wpłaty7Polimorfizm i nadpisywanie
Nadpisywanie metodWywoływanie metod klasy nadrzędnejTypowanie kaczeWspólny interfejsSprawdzanie typuPodsumowanie — role pracowników10Projekt: Menedżer kształtów
Konfiguracja projektuKlasa prostokątaKlasa kołaMetoda obwoduKolekcja kształtówPole całkowiteFiltrowanie kształtów2Wzorzec prototypu klasy
Koncepcja prototypuŁączenie za pomocą __indexKonstruktor :new()Inicjalizacja atrybutówNiezależne instancjePodsumowanie – fabryka samochodów5Przeciążanie operatorów w OOP
Dodawanie obiektówOdejmowanie obiektówŁączenie obiektówPorównywanie obiektów (<, >)Powtórka — działania na portfelu8Hermetyzacja
Konwencje nazewnictwaDomknięcia dla prywatnościDostęp za pomocą domknięćTabele tylko do odczytuLogika walidacjiPodsumowanie — bezpieczny sejf11Wzorce projektowe (podstawy)
Funkcje fabrykująceTabela SingletonWzorzec iteratoraObserwator (nasłuchujący)Powtórka — fabryka loggera3Stan i zachowanie obiektu
Zmienne instancjiMetody dostępoweMetody ustawiająceWłaściwości obliczaneFormatowanie ciągów znakówSprawdzanie równościPodsumowanie – ocena ucznia6Podstawy dziedziczenia
Konfiguracja dziedziczeniaDziedziczenie metodRozszerzanie konstruktoraDodawanie metod potomnychWspólne i unikalne elementyPowtórka — hierarchia kształtówPoćwicz samodzielnie: Kompilator Lua online