Variables de Instancia
Parte de la sección Programación Orientada a Objetos del Journey de Lua de Coddy. Lección 12 de 70.
Bienvenido a un nuevo capítulo centrado en cómo los objetos gestionan sus datos internos. Has aprendido a crear clases e instancias: ahora es el momento de explorar cómo cada instancia almacena y gestiona su propio estado único.
Las variables de instancia son campos que pertenecen exclusivamente a un único objeto. Cuando asignas un valor a self.something dentro de un método o constructor, esos datos viven únicamente en esa instancia particular. Otros objetos de la misma clase tienen sus propias copias independientes.
Esto se vuelve especialmente importante al almacenar datos complejos, como tablas. Considera un sistema de inventario en el que cada personaje lleva distintos objetos:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- Cada instancia obtiene su propia tabla vacía
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
endLa línea clave es instance.items = {}. Al crear una nueva tabla vacía dentro del constructor, cada objeto de inventario recibe su propia lista independiente. Si, en cambio, definieras items en la propia tabla de la clase, todas las instancias compartirían accidentalmente la misma tabla: ¡añadir una espada a un personaje se la daría a todos!
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- Salida: 1
print(#bag2.items) -- Salida: 1Cada inventario mantiene su propia colección. Este patrón se aplica siempre que una instancia necesite realizar un seguimiento de datos que cambian de forma independiente: listas, contadores o cualquier estado mutable exclusivo de ese objeto.
Desafío
FácilConstruyamos un sistema de ShoppingCart en el que cada carrito mantenga su propia lista independiente de productos. Esto demostrará cómo las variables de instancia mantienen los datos aislados entre objetos: ¡agregar artículos a un carrito no afectará a otro!
Organizarás tu código en dos archivos:
ShoppingCart.lua: Define tu claseShoppingCart, donde cada instancia tiene su propia tabla deproducts. Incluye:- Un constructor
:new()que inicialice una lista de productos vacía para cada carrito - Un método
:addProduct(productName)que agregue un producto a la lista de este carrito - Un método
:listProducts()que muestre cada producto en una línea separada
- Un constructor
main.lua: Requiere tu módulo ShoppingCart y crea dos carritos separados. Agrega productos diferentes a cada carrito para demostrar que mantienen inventarios independientes.
Recibirás cuatro entradas:
- Primer producto que se agregará al carrito A
- Segundo producto que se agregará al carrito A
- Primer producto que se agregará al carrito B
- Segundo producto que se agregará al carrito B
En tu archivo principal:
- Crea dos carritos de compras:
cartAycartB - Agrega los dos primeros productos a
cartA - Agrega los dos últimos productos a
cartB - Muestra
Cart A:después enumera los productos del carrito A - Muestra
Cart B:después enumera los productos del carrito B
Por ejemplo, si las entradas son Apple, Bread, Milk y Eggs, la salida debería ser:
Cart A:
Apple
Bread
Cart B:
Milk
EggsRecuerda: la clave es inicializar products como una nueva tabla vacía dentro del constructor. Esto garantiza que cada instancia del carrito obtenga su propia lista independiente, en lugar de compartir una tabla entre todos los carritos.
Pruébalo tú mismo
-- Requiere el módulo ShoppingCart
local ShoppingCart = require('ShoppingCart')
-- Lee las entradas
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()
-- TODO: Crea dos carritos de compras: cartA y cartB
-- TODO: Añade product1 y product2 a cartA
-- TODO: Añade product3 y product4 a cartB
-- TODO: Imprime "Cart A:" luego lista los productos de cartA
-- TODO: Imprime "Cart B:" luego lista los productos de cartB
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación Orientada a Objetos
1El concepto de 'self'
Tablas con funciones'self' explícitoLa sintaxis de dos puntosPunto vs. dos puntosResumen - Punto en movimiento4Proyecto: Banco Digital
Configuración del proyectoMétodo de depósito2Patrón de prototipo de clase
El concepto de prototipoVinculación con __indexEl constructor :new()Inicialización de atributosInstancias independientesResumen - Fábrica de coches5Sobrecarga de operadores en POO
Sumar objetosRestar objetosConcatenar objetosComparar objetos (<, >)Resumen - Matemáticas de la billetera8Encapsulamiento
Convenciones de nomenclaturaClosures para privacidadAcceso mediante ClosuresTablas de solo lecturaLógica de validaciónResumen - Bóveda segura11Patrones de diseño (Lite)
Funciones FactoryTabla SingletonPatrón IteradorObserver (Listener)Resumen - Logger Factory3Estado y Comportamiento de los Objetos
Variables de InstanciaMétodos GetterMétodos SetterPropiedades CalculadasFormateo de StringsComprobaciones de IgualdadResumen - Calificación del Estudiante6Fundamentos de la herencia
Configuración de la herenciaHerencia de métodosExtender el constructorAñadir métodos hijosCompartido vs. ÚnicoResumen: Jerarquía de formasPractica por tu cuenta: Compilador de Lua online