Zmienne instancji
Część sekcji Programowanie obiektowe ścieżki Lua w Coddy. Lekcja 12 z 70.
Witaj w nowym rozdziale poświęconym temu, jak obiekty zarządzają swoimi danymi wewnętrznymi. Wiesz już, jak tworzyć klasy i instancje: teraz czas dowiedzieć się, jak każda instancja przechowuje i zarządza swoim własnym, unikalnym stanem.
Zmienne instancji to pola należące wyłącznie do pojedynczego obiektu. Gdy przypisujesz wartość do self.something wewnątrz metody lub konstruktora, te dane istnieją tylko w tej konkretnej instancji. Inne obiekty tej samej klasy mają własne, oddzielne kopie.
Staje się to szczególnie ważne podczas przechowywania złożonych danych, takich jak tabele. Rozważ system ekwipunku, w którym każda postać nosi różne przedmioty:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- Każda instancja otrzymuje własną pustą tabelę
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
endKluczowa linia to instance.items = {}. Tworząc nową pustą tablicę wewnątrz konstruktora, każdy obiekt ekwipunku otrzymuje własną, odrębną listę. Jeśli zamiast tego zdefiniujesz items w samej tabeli klasy, wszystkie instancje przypadkowo współdzieliłyby tę samą tabelę: dodanie miecza jednej postaci dałoby go wszystkim!
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- Wynik: 1
print(#bag2.items) -- Wynik: 1Każdy magazyn utrzymuje własną kolekcję. Ten wzorzec ma zastosowanie zawsze, gdy instancja musi śledzić dane, które zmieniają się niezależnie: listy, liczniki lub dowolny zmienny stan unikalny dla danego obiektu.
Wyzwanie
ŁatwyZbudujmy system ShoppingCart, w którym każdy koszyk przechowuje własną, oddzielną listę produktów. Pokaże to, jak zmienne instancji izolują dane poszczególnych obiektów: dodanie produktów do jednego koszyka nie wpłynie na inny!
Rozmieścisz kod w dwóch plikach:
ShoppingCart.lua: Zdefiniuj klasęShoppingCart, której każda instancja ma własną tablicęproducts. Dodaj:- konstruktor
:new(), który inicjalizuje pustą listę produktów dla każdego koszyka - metodę
:addProduct(productName), która dodaje produkt do listy tego koszyka - metodę
:listProducts(), która wypisuje każdy produkt w osobnym wierszu
- konstruktor
main.lua: Załaduj moduł ShoppingCart i utwórz dwa oddzielne koszyki. Dodaj różne produkty do każdego koszyka, aby pokazać, że ich zawartość jest niezależna.
Otrzymasz cztery dane wejściowe:
- Pierwszy produkt do dodania do koszyka A
- Drugi produkt do dodania do koszyka A
- Pierwszy produkt do dodania do koszyka B
- Drugi produkt do dodania do koszyka B
W głównym pliku:
- Utwórz dwa koszyki:
cartAicartB - Dodaj dwa pierwsze produkty do
cartA - Dodaj dwa ostatnie produkty do
cartB - Wypisz
Cart A:, a następnie wyświetl produkty z koszyka A - Wypisz
Cart B:, a następnie wyświetl produkty z koszyka B
Na przykład, jeśli dane wejściowe to Apple, Bread, Milk i Eggs, wynikiem powinno być:
Cart A:
Apple
Bread
Cart B:
Milk
EggsPamiętaj: najważniejsze jest zainicjalizowanie products jako nowej, pustej tablicy wewnątrz konstruktora. Dzięki temu każda instancja koszyka otrzyma własną, oddzielną listę, zamiast współdzielić jedną tablicę ze wszystkimi koszykami.
Spróbuj swoich sił
-- Załaduj moduł ShoppingCart
local ShoppingCart = require('ShoppingCart')
-- Odczytaj dane wejściowe
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()
-- TODO: Utwórz dwa koszyki: cartA i cartB
-- TODO: Dodaj product1 i product2 do cartA
-- TODO: Dodaj product3 i product4 do cartB
-- TODO: Wyświetl "Cart A:", a następnie wypisz produkty z cartA
-- TODO: Wyświetl "Cart B:", a następnie wypisz produkty z cartB
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