Lua - Orientado a objetos

Introducción a la programación orientada a objetos

La programación orientada a objetos (OOP), es una de las técnicas de programación más utilizadas en la era moderna de la programación. Hay una serie de lenguajes de programación que admiten OOP que incluyen,

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

Características de OOP

  • Class - Una clase es una plantilla extensible para crear objetos, proporcionando valores iniciales para el estado (variables miembro) e implementaciones de comportamiento.

  • Objects - Es una instancia de clase y tiene una memoria separada asignada para sí mismo.

  • Inheritance - Es un concepto por el cual las variables y funciones de una clase son heredadas por otra clase.

  • Encapsulation- Es el proceso de combinar los datos y funciones dentro de una clase. Se puede acceder a los datos fuera de la clase con la ayuda de funciones. También se conoce como abstracción de datos.

POO en Lua

Puede implementar la orientación a objetos en Lua con la ayuda de tablas y funciones de primera clase de Lua. Al colocar funciones y datos relacionados en una tabla, se forma un objeto. La herencia se puede implementar con la ayuda de metatablas, proporcionando un mecanismo de búsqueda para funciones (métodos) y campos inexistentes en los objetos principales.

Las tablas en Lua tienen características de objeto como estado e identidad que es independiente de sus valores. Dos objetos (tablas) con el mismo valor son objetos diferentes, mientras que un objeto puede tener valores diferentes en momentos diferentes, pero siempre es el mismo objeto. Al igual que los objetos, las tablas tienen un ciclo de vida que es independiente de quién las creó o dónde se crearon.

Un ejemplo del mundo real

El concepto de orientación a objetos se usa ampliamente, pero es necesario comprenderlo claramente para obtener el máximo beneficio.

Consideremos un ejemplo matemático simple. A menudo nos encontramos con situaciones en las que trabajamos en diferentes formas como círculo, rectángulo y cuadrado.

Las formas pueden tener un área de propiedad común. Entonces, podemos extender otras formas desde la forma del objeto base con el área de propiedad común. Cada una de las formas puede tener sus propias propiedades y funciones, como un rectángulo puede tener propiedades length, width, area como propiedades y printArea y calculateArea como funciones.

Crear una clase simple

A continuación se muestra una implementación de clase simple para un rectángulo con tres propiedades de área, largo y ancho. También tiene una función printArea para imprimir el área calculada.

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

Crear un objeto

La creación de un objeto es el proceso de asignación de memoria para la instancia de clase. Cada uno de los objetos tiene su propia memoria y comparte los datos de clase comunes.

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

Accediendo a Propiedades

Podemos acceder a las propiedades en la clase usando el operador de punto como se muestra a continuación:

print(r.length)

Acceso a la función de miembro

Puede acceder a una función miembro utilizando el operador de dos puntos con el objeto como se muestra a continuación:

r:printArea()

Se asigna la memoria y se establecen los valores iniciales. El proceso de inicialización se puede comparar con constructores en otros lenguajes orientados a objetos. No es más que una función que permite configurar valores como se muestra arriba.

Ejemplo completo

Veamos un ejemplo completo usando la orientación a objetos en 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()

Cuando ejecute el programa anterior, obtendrá el siguiente resultado.

The area is 	100

Herencia en Lua

La herencia es el proceso de extender objetos básicos simples como formas a rectángulos, cuadrados, etc. A menudo se utiliza en el mundo real para compartir y ampliar las propiedades y funciones básicas.

Veamos una extensión de clase simple. Tenemos una clase como se muestra a continuación.

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

Podemos extender la forma a una clase cuadrada como se muestra a continuación.

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

Funciones básicas anuladas

Podemos anular las funciones de la clase base que es en lugar de usar la función en la clase base, la clase derivada puede tener su propia implementación como se muestra a continuación:

-- Derived class method printArea

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

Ejemplo completo de herencia

Podemos extender la implementación de la clase simple en Lua como se muestra arriba con la ayuda de otro método nuevo con la ayuda de metatablas. Todas las variables miembro y funciones de la clase base se conservan en la clase derivada.

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

Cuando ejecutamos el programa anterior, obtendremos el siguiente resultado:

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

En el ejemplo anterior, hemos creado dos clases derivadas: Rectángulo y Cuadrado a partir de la clase base Cuadrado. Es posible anular las funciones de la clase base en la clase derivada. En este ejemplo, la clase derivada anula la función printArea.