Menu
Coddy logo textTech

Variables de Instancia

Parte de la sección Object Oriented Programming 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 solo objeto. Cuando asignas un valor a self.something dentro de un método o constructor, esos datos viven solo en esa instancia en particular. Otros objetos de la misma clase tienen sus propias copias separadas.

Esto se vuelve especialmente importante al almacenar datos complejos como tablas. Considera un sistema de inventario donde cada personaje lleva diferentes 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)
end

La línea clave es instance.items = {}. Al crear una nueva tabla vacía dentro del constructor, cada objeto de inventario recibe su propia lista distinta. Si en su lugar 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: 1

Cada 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 único para ese objeto.

challenge icon

Desafío

Fácil

Vamos a construir un sistema de ShoppingCart donde cada carrito mantenga su propia lista separada 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 clase ShoppingCart donde cada instancia tenga su propia tabla products. 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 imprima cada producto en una línea separada
  • main.lua: Requiere tu módulo ShoppingCart y crea dos carritos separados. Agrega diferentes productos a cada carrito para demostrar que mantienen inventarios independientes.

Recibirás cuatro entradas:

  1. Primer producto para agregar al carrito A
  2. Segundo producto para agregar al carrito A
  3. Primer producto para agregar al carrito B
  4. Segundo producto para agregar al carrito B

En tu archivo principal:

  1. Crea dos carritos de compras: cartA y cartB
  2. Agrega los dos primeros productos a cartA
  3. Agrega los dos últimos productos a cartB
  4. Imprime Cart A: y luego enumera los productos del carrito A
  5. Imprime Cart B: y luego 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
Eggs

Recuerda: la clave es inicializar products como una nueva tabla vacía dentro del constructor. Esto asegura que cada instancia del carrito obtenga su propia lista separada en lugar de compartir una sola tabla entre todos los carritos.

Hoja de referencia

Las variables de instancia son campos que pertenecen exclusivamente a un solo objeto. Cuando asignas un valor a self.something dentro de un método o constructor, esos datos viven solo en esa instancia en particular.

Para crear variables de instancia, inicialízalas dentro del constructor utilizando una nueva tabla para cada instancia:

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

La clave es instance.items = {}; crear una nueva tabla vacía dentro del constructor asegura que cada objeto reciba sus propios datos distintos. Si definieras items en la propia tabla de la clase, todas las instancias compartirían la misma tabla.

local bag1 = Inventory:new()
local bag2 = Inventory:new()

bag1:addItem("Sword")
bag2:addItem("Potion")

print(#bag1.items)  -- Output: 1
print(#bag2.items)  -- Output: 1

Cada instancia mantiene su propia colección de forma independiente. Este patrón se aplica a cualquier estado mutable único de un objeto: listas, contadores u otros datos que cambian por instancia.

Pruébalo tú mismo

-- Requerir el módulo ShoppingCart
local ShoppingCart = require('ShoppingCart')

-- Leer entradas
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()

-- TODO: Crear dos carritos de compras: cartA y cartB

-- TODO: Agregar product1 y product2 a cartA

-- TODO: Agregar product3 y product4 a cartB

-- TODO: Imprimir "Cart A:" luego listar los productos de cartA

-- TODO: Imprimir "Cart B:" luego listar los productos de cartB
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming