Lua - Object Oriented

Introduzione a OOP

La programmazione orientata agli oggetti (OOP) è una delle tecniche di programmazione più utilizzate nell'era moderna della programmazione. Esistono numerosi linguaggi di programmazione che supportano l'OOP che includono,

  • C++
  • Java
  • Objective-C
  • Smalltalk
  • C#
  • Ruby

Caratteristiche di OOP

  • Class - Una classe è un modello estensibile per la creazione di oggetti, che fornisce valori iniziali per lo stato (variabili membro) e implementazioni del comportamento.

  • Objects - È un'istanza di classe e ha una memoria separata allocata per se stessa.

  • Inheritance - È un concetto in base al quale le variabili e le funzioni di una classe vengono ereditate da un'altra classe.

  • Encapsulation- È il processo di combinazione dei dati e delle funzioni all'interno di una classe. È possibile accedere ai dati al di fuori della classe con l'aiuto delle funzioni. È anche noto come astrazione dei dati.

OOP a Lua

Puoi implementare l'orientamento agli oggetti in Lua con l'aiuto di tabelle e funzioni di prima classe di Lua. Inserendo funzioni e dati correlati in una tabella, viene formato un oggetto. L'ereditarietà può essere implementata con l'aiuto di metatables, fornendo un meccanismo di ricerca per funzioni (metodi) e campi inesistenti negli oggetti padre.

Le tabelle in Lua hanno le caratteristiche di un oggetto come lo stato e l'identità che è indipendente dai suoi valori. Due oggetti (tabelle) con lo stesso valore sono oggetti diversi, mentre un oggetto può avere valori diversi in momenti diversi, ma è sempre lo stesso oggetto. Come gli oggetti, le tabelle hanno un ciclo di vita indipendente da chi le ha create o da dove sono state create.

Un esempio del mondo reale

Il concetto di orientamento agli oggetti è ampiamente utilizzato ma è necessario comprenderlo chiaramente per ottenere un beneficio adeguato e massimo.

Consideriamo un semplice esempio di matematica. Spesso ci imbattiamo in situazioni in cui lavoriamo su forme diverse come cerchio, rettangolo e quadrato.

Le forme possono avere una proprietà comune Area. Quindi, possiamo estendere altre forme dalla forma dell'oggetto base con l'area delle proprietà comuni. Ciascuna delle forme può avere le proprie proprietà e funzioni come un rettangolo può avere proprietà length, width, area come sue proprietà e printArea e calcolaArea come sue funzioni.

Creazione di una classe semplice

Di seguito è mostrata una semplice implementazione di classe per un rettangolo con tre proprietà area, length e width. Ha anche una funzione printArea per stampare l'area calcolata.

-- 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

Creazione di un oggetto

La creazione di un oggetto è il processo di allocazione della memoria per l'istanza della classe. Ciascuno degli oggetti ha la propria memoria e condivide i dati della classe comune.

r = Rectangle:new(nil,10,20)

Accesso alle proprietà

Possiamo accedere alle proprietà nella classe utilizzando l'operatore punto come mostrato di seguito -

print(r.length)

Accesso alla funzione membro

È possibile accedere a una funzione membro utilizzando l'operatore due punti con l'oggetto come mostrato di seguito:

r:printArea()

La memoria viene allocata e vengono impostati i valori iniziali. Il processo di inizializzazione può essere paragonato a costruttori in altri linguaggi orientati agli oggetti. Non è altro che una funzione che consente di impostare i valori come mostrato sopra.

Esempio completo

Vediamo un esempio completo usando l'orientamento agli oggetti in 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()

Quando esegui il programma sopra, otterrai il seguente output.

The area is 	100

Eredità in Lua

L'ereditarietà è il processo di estensione di oggetti di base semplici come la forma a rettangoli, quadrati e così via. Viene spesso utilizzato nel mondo reale per condividere ed estendere le proprietà e le funzioni di base.

Vediamo una semplice estensione di classe. Abbiamo una classe come mostrato di seguito.

-- 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

Possiamo estendere la forma a una classe quadrata come mostrato di seguito.

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

Funzioni di base di over-riding

Possiamo sovrascrivere le funzioni della classe base che invece di utilizzare la funzione nella classe base, la classe derivata può avere la propria implementazione come mostrato di seguito -

-- Derived class method printArea

function Square:printArea ()
   print("The area of square is ",self.area)
end

Esempio completo di ereditarietà

Possiamo estendere la semplice implementazione della classe in Lua come mostrato sopra con l'aiuto di un altro nuovo metodo con l'aiuto dei metatables. Tutte le variabili membro e le funzioni della classe base vengono mantenute nella classe derivata.

-- 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()

Quando eseguiamo il programma sopra, otterremo il seguente output:

The area is 	100
The area of square is 	100
The area of Rectangle is 	200

Nell'esempio sopra, abbiamo creato due classi derivate: Rectangle e Square dalla classe di base Square. È possibile sovrascrivere le funzioni della classe base nella classe derivata. In questo esempio, la classe derivata sovrascrive la funzione printArea.