Lua - zorientowany obiektowo
Wprowadzenie do OOP
Programowanie obiektowe (OOP) to jedna z najczęściej używanych technik programowania, która jest używana we współczesnej erze programowania. Istnieje wiele języków programowania obsługujących OOP, które obejmują:
- C++
- Java
- Objective-C
- Smalltalk
- C#
- Ruby
Funkcje OOP
Class - Klasa to rozszerzalny szablon do tworzenia obiektów, dostarczający początkowych wartości dla stanu (zmienne składowe) i implementacji zachowania.
Objects - Jest instancją klasy i ma przydzieloną dla siebie oddzielną pamięć.
Inheritance - Jest to koncepcja, dzięki której zmienne i funkcje jednej klasy są dziedziczone przez inną klasę.
Encapsulation- Jest to proces łączenia danych i funkcji wewnątrz klasy. Dostęp do danych można uzyskać poza klasą za pomocą funkcji. Nazywa się to również abstrakcją danych.
OOP w Lua
Możesz zaimplementować obiektową orientację w Lua za pomocą tabel i funkcji pierwszej klasy Lua. Po umieszczeniu funkcji i powiązanych danych w tabeli tworzony jest obiekt. Dziedziczenie można zaimplementować za pomocą metatabli, udostępniając mechanizm wyszukiwania dla nieistniejących funkcji (metod) i pól w obiektach nadrzędnych.
Tabele w Lua mają cechy obiektu, takie jak stan i tożsamość, które są niezależne od jego wartości. Dwa obiekty (tabele) o tej samej wartości są różnymi obiektami, podczas gdy obiekt może mieć różne wartości w różnym czasie, ale zawsze jest to ten sam obiekt. Podobnie jak obiekty, tabele mają cykl życia, który jest niezależny od tego, kto je stworzył lub gdzie zostały utworzone.
Przykład z prawdziwego świata
Pojęcie orientacji obiektowej jest szeroko stosowane, ale aby uzyskać właściwe i maksymalne korzyści, należy je dokładnie zrozumieć.
Rozważmy prosty przykład matematyczny. Często spotykamy się z sytuacjami, w których pracujemy nad różnymi kształtami, takimi jak koło, prostokąt i kwadrat.
Kształty mogą mieć wspólną właściwość Area. Zatem możemy rozszerzyć inne kształty z podstawowego kształtu obiektu za pomocą wspólnego obszaru właściwości. Każdy z kształtów może mieć swoje własne właściwości, a funkcje, takie jak prostokąt, mogą mieć właściwości długość, szerokość, obszar jako jego właściwości oraz printArea i ObliczArea jako jego funkcje.
Tworzenie prostej klasy
Poniżej przedstawiono prostą implementację klasy dla prostokąta z trzema właściwościami: obszar, długość i szerokość. Posiada również funkcję printArea do drukowania obliczonego obszaru.
-- Meta class
Rectangle = {area = 0, length = 0, breadth = 0}
-- Derived class method new
function Rectangle:new (o,length,breadth)
o = o or {}
setmetatable(o, self)
self.__index = self
self.length = length or 0
self.breadth = breadth or 0
self.area = length*breadth;
return o
end
-- Derived class method printArea
function Rectangle:printArea ()
print("The area of Rectangle is ",self.area)
end
Tworzenie obiektu
Tworzenie obiektu to proces przydzielania pamięci dla instancji klasy. Każdy z obiektów ma własną pamięć i ma wspólne dane klasowe.
r = Rectangle:new(nil,10,20)
Dostęp do właściwości
Możemy uzyskać dostęp do właściwości w klasie za pomocą operatora kropki, jak pokazano poniżej -
print(r.length)
Dostęp do funkcji członka
Możesz uzyskać dostęp do funkcji składowej za pomocą operatora dwukropka z obiektem, jak pokazano poniżej -
r:printArea()
Pamięć zostaje przydzielona i ustawiane są wartości początkowe. Proces inicjalizacji można porównać do konstruktorów w innych językach obiektowych. To nic innego jak funkcja, która umożliwia ustawienie wartości, jak pokazano powyżej.
Kompletny przykład
Przyjrzyjmy się kompletnemu przykładowi użycia orientacji obiektowej w Lua.
-- Meta class
Shape = {area = 0}
-- Base class method new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- Base class method printArea
function Shape:printArea ()
print("The area is ",self.area)
end
-- Creating an object
myshape = Shape:new(nil,10)
myshape:printArea()
Po uruchomieniu powyższego programu otrzymasz następujące dane wyjściowe.
The area is 100
Dziedziczenie w Lua
Dziedziczenie to proces rozszerzania prostych obiektów podstawowych, takich jak kształt, na prostokąty, kwadraty i tak dalej. Jest często używany w świecie rzeczywistym do udostępniania i rozszerzania podstawowych właściwości i funkcji.
Zobaczmy proste rozszerzenie klasy. Mamy klasę, jak pokazano poniżej.
-- Meta class
Shape = {area = 0}
-- Base class method new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- Base class method printArea
function Shape:printArea ()
print("The area is ",self.area)
end
Możemy rozszerzyć kształt do klasy kwadratowej, jak pokazano poniżej.
Square = Shape:new()
-- Derived class method new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
Podstawowe funkcje bazowe
Możemy przesłonić funkcje klasy bazowej, które zamiast używać funkcji w klasie bazowej, klasa pochodna może mieć własną implementację, jak pokazano poniżej -
-- Derived class method printArea
function Square:printArea ()
print("The area of square is ",self.area)
end
Przykład pełnego dziedziczenia
Możemy rozszerzyć prostą implementację klasy w Lua, jak pokazano powyżej, przy pomocy innej nowej metody z pomocą metatabel. Wszystkie zmienne składowe i funkcje klasy bazowej są zachowywane w klasie pochodnej.
-- Meta class
Shape = {area = 0}
-- Base class method new
function Shape:new (o,side)
o = o or {}
setmetatable(o, self)
self.__index = self
side = side or 0
self.area = side*side;
return o
end
-- Base class method printArea
function Shape:printArea ()
print("The area is ",self.area)
end
-- Creating an object
myshape = Shape:new(nil,10)
myshape:printArea()
Square = Shape:new()
-- Derived class method new
function Square:new (o,side)
o = o or Shape:new(o,side)
setmetatable(o, self)
self.__index = self
return o
end
-- Derived class method printArea
function Square:printArea ()
print("The area of square is ",self.area)
end
-- Creating an object
mysquare = Square:new(nil,10)
mysquare:printArea()
Rectangle = Shape:new()
-- Derived class method new
function Rectangle:new (o,length,breadth)
o = o or Shape:new(o)
setmetatable(o, self)
self.__index = self
self.area = length * breadth
return o
end
-- Derived class method printArea
function Rectangle:printArea ()
print("The area of Rectangle is ",self.area)
end
-- Creating an object
myrectangle = Rectangle:new(nil,10,20)
myrectangle:printArea()
Po uruchomieniu powyższego programu otrzymamy następujące dane wyjściowe -
The area is 100
The area of square is 100
The area of Rectangle is 200
W powyższym przykładzie utworzyliśmy dwie klasy pochodne - Rectangle i Square z klasy bazowej Square. Istnieje możliwość przesłonięcia funkcji klasy bazowej w klasie pochodnej. W tym przykładzie klasa pochodna przesłania funkcję printArea.