Nadpisywanie metod
Część sekcji Programowanie obiektowe ścieżki Lua w Coddy. Lekcja 37 z 70.
Do tej pory klasy potomne dziedziczyły metody klas nadrzędnych i dodawały nowe. Ale co, jeśli klasa potomna potrzebuje tej samej nazwy metody, ale innego działania? Nazywa się to przesłanianiem metod.
Gdy definiujesz metodę w klasie potomnej o tej samej nazwie co metoda w klasie nadrzędnej, pierwszeństwo ma wersja z klasy potomnej. Łańcuch wyszukiwania w Lua najpierw sprawdza klasę potomną i jeśli znajdzie tam metodę, przestaje szukać.
local Animal = {}
Animal.__index = Animal
function Animal:new(name)
local obj = {name = name}
setmetatable(obj, Animal)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- Dog nadpisuje speak()
local Dog = {}
Dog.__index = Dog
setmetatable(Dog, {__index = Animal})
function Dog:new(name)
local obj = Animal.new(Animal, name)
setmetatable(obj, Dog)
return obj
end
function Dog:speak()
print(self.name .. " barks: Woof!")
endTeraz każda klasa reaguje inaczej na to samo wywołanie metody:
local generic = Animal:new("Creature")
local buddy = Dog:new("Buddy")
generic:speak() -- Wynik: Creature wydaje dźwięk
buddy:speak() -- Wynik: Buddy szczeka: Hau!Metoda :speak() klasy Dog całkowicie zastępuje wersję odziedziczoną po klasie nadrzędnej w przypadku instancji Dog. Dzięki temu możesz tworzyć wyspecjalizowane zachowania, zachowując spójny interfejs: każde zwierzę może :speak(), ale każdy gatunek robi to inaczej.
Wyzwanie
ŁatwyStwórzmy małe królestwo zwierząt, w którym różne stworzenia odzywają się na swój wyjątkowy sposób! Utworzysz klasę bazową Animal oraz dwie klasy potomne: Cat i Cow. Każda z nich przesłoni metodę :speak() klasy bazowej, nadając jej własne działanie.
Rozmieścisz swój kod w czterech plikach:
Animal.lua: Twoja klasa bazowa z konstruktorem:new(name), który zapisuje imię zwierzęcia. Dodaj metodę:speak(), która wypisuje imię zwierzęcia, a po nimmakes a sound. To domyślne działanie, które klasy potomne przesłonią.Cat.lua: Klasa potomna dziedzicząca po Animal. Jej konstruktor:new(name)powinien wywołać konstruktor klasy bazowej, a następnie ponownie powiązać metatabelę z Cat. Przesłoń metodę:speak(), aby koty odzywały się inaczej: wypisz imię kota, a po nimmeows: Meow!Cow.lua: Kolejna klasa potomna dziedzicząca po Animal. Skonfiguruj konstruktor tak samo jak w Cat. Przesłoń metodę:speak(), aby krowy wypisywały swoje imię, a po nimmoos: Moo!main.lua: Połącz wszystko w całość! Odczytaj z wejścia dwa imiona, utwórz Cat z pierwszym imieniem i Cow z drugim, a następnie wywołaj:speak()dla każdego z nich, aby pokazać, że ta sama nazwa metody daje różne wyniki w zależności od klasy.
Otrzymasz dwa dane wejściowe:
- Imię kota
- Imię krowy
W pliku głównym utwórz oba zwierzęta i najpierw wywołaj :speak() dla kota, a potem dla krowy.
Na przykład, jeśli danymi wejściowymi są Whiskers i Bessie, wynikiem powinno być:
Whiskers meows: Meow!
Bessie moos: Moo!Zauważ, że oba zwierzęta reagują na to samo wywołanie metody :speak(), ale każde wypisuje tekst właściwy dla swojego typu. Wersja Cat całkowicie zastępuje ogólne działanie klasy bazowej makes a sound, podobnie jak wersja Cow. To właśnie przesłanianie metod: ten sam interfejs, różne implementacje!
Spróbuj swoich sił
-- main.lua: Połącz wszystko w całość
local Cat = require('Cat')
local Cow = require('Cow')
-- Odczytaj dane wejściowe
local catName = io.read()
local cowName = io.read()
-- TODO: Utwórz obiekt Cat z pierwszym imieniem
-- TODO: Utwórz obiekt Cow z drugim imieniem
-- TODO: Wywołaj :speak() najpierw dla kota, a potem dla krowy
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