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.