Nastoletni
Programiści

Logo Nastoletnich Programistów

Obiektowość w Lua

Podejście obiektowe w programowaniu na zawsze zmieniło podejście do kreowania kodu w wielu językach. Możliwość podziału programu na obiekty komunikujące się między sobą w celu rozwiązania problemu ma wiele zalet, co potwierdza popularność tego paradygmatu wśród programistów. Co jednak zrobić w sytuacji, w której język nie jest językiem zorientowanym obiektowo, a jednak chcielibyśmy skorzystać z tego paradygmatu? W tym artykule pochylę się nad językiem Lua. Zapraszam do lektury. 🙂

Język Lua nie udostępnia wprost możliwości działania na obiektach. Jest za to jedna z możliwości, jak taki sposób uzyskać. Z pomocą przychodzą nam metatablice. Jako, iż wikipedia nie jest zbyt wymowna na ich temat, pozwolę sobie skonstruować prostą do zrozumienia definicję na potrzebę ów artykułu. 🙂

Metatablice są to tablice zawierające określony zestaw zachowań, na które jest w stanie zareagować wartość. Każda wartość ma swoją metatablicę, która reguluje to, w jaki sposób np. liczba 5 zareaguje na próbę wykonania na niej operacji dodawania.

Znając teraz uproszczoną definicję metatablicy, możemy przejść przez kawałek teorii związanej z tym zagadnieniem. W Lua mamy do czynienia z prostą dwuwymiarową tablicą, która jest wywoływana przez interpreter w każdym przypadku, gdy coś wyda mu się nie do końca poprawne. Weźmy sobie za przykład wartość nieliczbową, np. tablicę jednowymiarową. Co się stanie, gdy nasza tablica zostanie operandem dodawania? Interpreter zwróci uwagę na to, że chcemy dodać do czegoś wartość nieliczbową i zwróci się do metatablicy podając zdarzenie add. Metatablica zwróci za to metametodę (wartość pod kluczem __add) odpowiadającą temu zdarzeniu, co pozwoli nam (lub nie, w zależności od tego czy metametoda istnieje) wykonać operację dodawania na tej wartości. Zrzucając szatę możliwego niezrozumienia pojęć pozwolę sobie wytłumaczyć użyte przeze mnie dwa nowe pojęcia. Zdarzenie to po prostu klucz tablicy, a metametoda to funkcja, która zostanie wykonana w przypadku wywołania danego zdarzenia. Brzmi znajomo? Już za moment wszystko powinno stać się zrozumiałe.

Szukając porówniania do innych języków, przykładem dla nas mogą okazać się przeciążenia operatorów w języku C#. Idea działania jest praktycznie taka sama.

Jeżeli teraz połączymy te informację z inną, która mówi nam, że te metatablice można, tak jak w językach typu C#, przeciążać, to dojdziemy do wniosku, że z dużą dozą prawdopodobieństwa uda nam się napisać bardzo dobrze działający „kod zorientowany obiektowo”. Możemy teraz przejść do praktycznej części. 🙂

Źródło: http://www.ntu.edu.sg/home/ehchua/programming/cpp/cp3_OOP.html

Rozpocznijmy naszą praktykę od utworzenia metatablicy oraz nadpisania jej zdarzenia.

Utworzyliśmy teraz metatablicę Account, której wartość zdarzenia index ustawiliśmy na nią samą. Dzięki czemu obiekty będą mogły korzystać z metod zdefiniowanych w tej tablicy. Na tym jednak nie poprzestajemy.

Tym razem zdefiniowaliśmy metodę create, która pozwoli nam na utworzenie „obiektu” naszej tablicy. Nasz trik polega na utworzeniu pustej tablicy, której wstrzykniemy naszą spreparowaną metatablicę. Następna linijka odpowiada za „konstruktor” naszego obiektu, czyli zapisanie właściwości balance przekazanej z wywołaniem metody create. Na sam koniec zwracamy nowo utworzony „obiekt”. Nie mielibyśmy jednak obiektu, gdyby nie chociaż jedna metoda poza konstruktorem. Utwórzmy więc takową.

Prosta metoda umożliwiająca podanie w argumencie liczby o którą uszczuplimy właściwość balance naszego obiektu. Skorzystaliśmy sobie w niej z parametru self, który umożliwia nam ominięcie odniesienia do globalnej wartości Account. Jest to dobra praktyka, która warto sobie przyswoić.

Jeżeli jesteś osobą, która lepiej czuje się z użyciem parametru this niż self, istnieje możliwość zmiany tego parametru. W tym celu, przy tworzeniu definicji metody, zamiast : korzystamy z operatora .. Wówczas w pierwszym argumencie możemy wpisać this lub cokolwiek innego, dzięki czemu zmienna ta stanie się reprezentacją naszego obiektu w tej definicji.

Do testów starczy nam to w zupełności. Utwórzmy teraz jeden obiekt i skorzystajmy z metody.

Prześledźmy teraz działanie tych dwóch linijek kodu, aby lepiej zrozumieć co się stanie. Pierwsza linijka to po prostu utworzenie obiektu na bazie klasy Account. Działanie tej metody wytłumaczyliśmy sobie parę akapitów wyżej. Druga linijka natomiast nie jest tak oczywista jak mogłoby się wydawać. Odwołanie do metody tablicy acc zwróci błąd, ponieważ nic takiego nie istnieje. Interpreter wie natomiast, że acc to tablica, tak więc podejmie próbę wyszukania indeksu tej tablicy. I tutaj wkracza do akcji przygotowana przez nas metatablica, która umożliwia nam dostanie się do zasobów tablicy Account. I tym sposobem utworzyliśmy nasz pierwszy pełnoprawny obiekt w języku Lua! 🙂

Czy istnieje jednak prostsze podejście do obiektowości w Lua? Okazuje się, że tak. Co więcej, być może uda nam się nawet użyć dziedziczenia! To jednak materiał na kolejny artykuł.


Artykuł bazujący na zawartości strony: http://lua-users.org/wiki/SimpleLuaClasses

FireHead996

Full Stack Developer. Lubi pomagać innych w zrozumieniu programowania, ale też sam nie stroni od pomocy innych. Prowadzi mały kanał w serwisie YouTube.

Zobacz wszystkie posty tego autora →

Komentarze