LUA no tiene soporte nativo para la Programación Orientada a Objetos (POO), pero ofrece suficiente flexibilidad para implementarla utilizando tablas y metatables. En este tema, veremos cómo simular clases, objetos, herencia y otros conceptos clave de la POO en LUA.
6.1. Simulación de Clases y Objetos 🏛️
En LUA, se puede simular una clase usando una tabla. Los métodos de la clase se definen como funciones dentro de la tabla.
6.1.1. Creación de una clase
Para crear una clase, definimos una tabla y un constructor que inicialice sus propiedades.
-- Definimos la clase "Persona"
Persona = {}
Persona.__index = Persona
-- Constructor
function Persona:new(nombre, edad)
local obj = {
nombre = nombre or "Sin nombre",
edad = edad or 0
}
setmetatable(obj, Persona)
return obj
end
-- Método para mostrar información
function Persona:presentarse()
print("Hola, soy " .. self.nombre .. " y tengo " .. self.edad .. " años.")
end
6.1.2. Creación de objetos
Usamos el constructor de la clase para crear instancias (objetos) de la clase.
-- Creamos un objeto de la clase Persona
local persona1 = Persona:new("Laura", 30)
persona1:presentarse() -- Salida: Hola, soy Laura y tengo 30 años.
-- Creamos otro objeto con diferentes valores
local persona2 = Persona:new("Carlos", 25)
persona2:presentarse() -- Salida: Hola, soy Carlos y tengo 25 años.
6.1.3. Añadir métodos adicionales
Podemos agregar más métodos a la clase para ampliar su funcionalidad.
-- Añadimos un método para cambiar el nombre
function Persona:cambiarNombre(nuevoNombre)
self.nombre = nuevoNombre
end
-- Usamos el nuevo método
persona1:cambiarNombre("Ana")
persona1:presentarse() -- Salida: Hola, soy Ana y tengo 30 años.
6.2. Herencia y Polimorfismo 🧬
La herencia en LUA se puede simular haciendo que una tabla "clase hija" tenga como metatable la "clase padre". Esto permite que la clase hija herede métodos y propiedades de la clase padre.
6.2.1. Creación de una subclase
Creamos una subclase Estudiante que herede de Persona.
-- Definimos la subclase "Estudiante"
Estudiante = Persona:new()
Estudiante.__index = Estudiante
-- Constructor de la subclase
function Estudiante:new(nombre, edad, carrera)
local obj = Persona:new(nombre, edad)
setmetatable(obj, Estudiante)
obj.carrera = carrera or "Sin carrera"
return obj
end
-- Método específico de Estudiante
function Estudiante:presentarse()
print("Hola, soy " .. self.nombre .. ", tengo " .. self.edad .. " años, y estudio " .. self.carrera .. ".")
end
6.2.2. Uso de la subclase
Creamos un objeto de la subclase y usamos sus métodos.
local estudiante1 = Estudiante:new("María", 22, "Ingeniería")
estudiante1:presentarse() -- Salida: Hola, soy María, tengo 22 años, y estudio Ingeniería.
6.2.3. Sobrescribir métodos
La subclase puede sobrescribir métodos de la clase padre para ofrecer un comportamiento especializado.
-- Método presentarse de Estudiante sobrescribe el de Persona
function Estudiante:presentarse()
print("Soy " .. self.nombre .. ", estudio " .. self.carrera .. " y tengo " .. self.edad .. " años.")
end
-- Usamos el método sobrescrito
estudiante1:presentarse() -- Salida: Soy María, estudio Ingeniería y tengo 22 años.
6.3. Encapsulamiento y Visibilidad de Miembros 🔒
En LUA, no existe un mecanismo nativo para definir la visibilidad de los miembros (públicos, privados, protegidos). Sin embargo, se pueden simular usando convenciones y closures.
6.3.1. Propiedades privadas con closures
Podemos simular propiedades privadas utilizando closures y funciones locales.
-- Definimos una clase con propiedades privadas
CuentaBancaria = {}
CuentaBancaria.__index = CuentaBancaria
function CuentaBancaria:new(saldoInicial)
local saldo = saldoInicial or 0 -- Esta es una propiedad "privada"
local obj = {}
setmetatable(obj, CuentaBancaria)
function obj:depositar(monto)
saldo = saldo + monto
end
function obj:retirar(monto)
if monto <= saldo then
saldo = saldo - monto
else
print("Fondos insuficientes")
end
end
function obj:consultarSaldo()
return saldo
end
return obj
end
-- Usamos la clase con propiedades privadas
local cuenta = CuentaBancaria:new(100)
cuenta:depositar(50)
print("Saldo: " .. cuenta:consultarSaldo()) -- Salida: Saldo: 150
cuenta:retirar(20)
print("Saldo: " .. cuenta:consultarSaldo()) -- Salida: Saldo: 130
6.3.2. Métodos privados
También podemos definir métodos privados utilizando funciones locales dentro del constructor.
function CuentaBancaria:new(saldoInicial)
local saldo = saldoInicial or 0
local function calcularInteres()
return saldo * 0.05
end
local obj = {}
setmetatable(obj, CuentaBancaria)
function obj:depositar(monto)
saldo = saldo + monto + calcularInteres()
end
function obj:consultarSaldo()
return saldo
end
return obj
end
-- Usamos el método privado
cuenta:depositar(100)
print("Saldo con interés: " .. cuenta:consultarSaldo()) -- Salida: Saldo con interés: 235
6.4. Uso de Metatables en la Programación Orientada a Objetos 🧩
Las metatables son un aspecto avanzado en LUA que se pueden usar para modificar el comportamiento de las tablas, permitiendo una implementación más flexible de la POO.
6.4.1. Sobrecarga de operadores
Podemos usar metatables para sobrecargar operadores, como sumar dos objetos.
-- Definimos la clase "Vector"
Vector = {}
Vector.__index = Vector
function Vector:new(x, y)
local obj = {x = x, y = y}
setmetatable(obj, Vector)
return obj
end
-- Sobrecargamos el operador "+"
function Vector.__add(v1, v2)
return Vector:new(v1.x + v2.x, v1.y + v2.y)
end
-- Usamos la sobrecarga de operadores
local v1 = Vector:new(2, 3)
local v2 = Vector:new(4, 5)
local v3 = v1 + v2
print("Resultado: (" .. v3.x .. ", " .. v3.y .. ")") -- Salida: Resultado: (6, 8)
6.4.2. Métodos metamágicos útiles
Además de __add, LUA soporta otros métodos metamágicos para implementar diferentes comportamientos personalizados en las clases.
__tostring: Define cómo se muestra un objeto cuando se convierte en una cadena.
__call: Permite que un objeto se comporte como una función.
function Vector:__call()
return self.x, self.y
end
local x, y = v3()
print("Coordenadas: " .. x .. ", " .. y) -- Salida: Coordenadas: 6, 8
Este bloque de código contiene todo el contenido del Tema 6 sobre la Programación Orientada a Objetos en LUA, en un formato que puedes copiar y pegar fácilmente. ¡Espero que te sea útil para avanzar en tu comprensión de LUA y la POO! 😊