Instancias independientes
Parte de la sección Object Oriented Programming del Journey de Lua de Coddy — lección 10 de 70.
Un aspecto crucial de la programación orientada a objetos es que cada instancia mantiene su propio estado independiente. Cuando creas dos objetos a partir de la misma clase, son completamente independientes; cambiar uno no afecta al otro.
Considera este ejemplo:
local Counter = {}
Counter.__index = Counter
function Counter:new(start)
local instance = {}
setmetatable(instance, self)
instance.value = start or 0
return instance
end
function Counter:increment()
self.value = self.value + 1
end
-- Crear dos contadores separados
local counterA = Counter:new(10)
local counterB = Counter:new(5)
counterA:increment()
counterA:increment()
print(counterA.value) -- Salida: 12
print(counterB.value) -- Salida: 5Aunque ambos contadores provienen de la misma clase Counter, incrementar counterA no tiene efecto en counterB. Cada objeto tiene su propio campo value almacenado en su propia tabla de instancias.
Esta independencia es lo que hace que los objetos sean útiles. Puedes crear docenas de jugadores en un juego, cada uno haciendo un seguimiento de su propia salud y puntuación. Puedes gestionar múltiples cuentas bancarias, cada una con un saldo diferente.
La clase define la estructura y el comportamiento, pero cada instancia vive su propia vida con sus propios datos.
Desafío
Fácil¡Vamos a demostrar que los objetos de la misma clase realmente viven vidas independientes! Construirás una clase Wallet y crearás dos instancias de billetera separadas, luego las modificarás de forma independiente para demostrar que los cambios en una no afectan a la otra.
Organizarás tu código en dos archivos:
Wallet.lua: Define tu claseWalletcon el patrón de constructor estándar. Cada billetera debe rastrear su propiobalance. Incluye:- Un constructor
:new(startingBalance)que inicializa la billetera con la cantidad dada - Un método
:add(amount)que aumenta el saldo - Un método
:spend(amount)que disminuye el saldo
- Un constructor
main.lua: Requiere tu módulo Wallet y crea dos instancias de billetera separadas. Realiza diferentes operaciones en cada una para mostrar que mantienen un estado independiente.
Recibirás cuatro entradas:
- Saldo inicial para la billetera A
- Saldo inicial para la billetera B
- Cantidad a añadir a la billetera A
- Cantidad a gastar de la billetera B
En tu archivo principal:
- Crea
walletAcon el primer saldo inicial - Crea
walletBcon el segundo saldo inicial - Añade la cantidad especificada a
walletA - Gasta la cantidad especificada de
walletB - Imprime ambos saldos en líneas separadas
Imprime los saldos finales en este formato exacto:
Wallet A: [balance]
Wallet B: [balance]Por ejemplo, si las entradas son 100, 50, 25, y 10, la salida debería ser:
Wallet A: 125
Wallet B: 40Observa cómo añadir a la billetera A no cambia la billetera B, y gastar de la billetera B no afecta a la billetera A; cada instancia mantiene su propio saldo por separado.
Hoja de referencia
Cada instancia de una clase mantiene su propio estado independiente. Crear múltiples objetos a partir de la misma clase da como resultado instancias completamente independientes; modificar una no afecta a las demás.
Ejemplo que demuestra la independencia de las instancias:
local Counter = {}
Counter.__index = Counter
function Counter:new(start)
local instance = {}
setmetatable(instance, self)
instance.value = start or 0
return instance
end
function Counter:increment()
self.value = self.value + 1
end
-- Create two separate counters
local counterA = Counter:new(10)
local counterB = Counter:new(5)
counterA:increment()
counterA:increment()
print(counterA.value) -- Output: 12
print(counterB.value) -- Output: 5Cada objeto tiene su propia tabla de instancia que almacena sus propios datos. La clase define la estructura y el comportamiento, pero cada instancia mantiene un estado independiente.
Pruébalo tú mismo
-- Requerir el módulo Wallet
local Wallet = require('Wallet')
-- Leer entradas
local startingA = tonumber(io.read())
local startingB = tonumber(io.read())
local addAmount = tonumber(io.read())
local spendAmount = tonumber(io.read())
-- TODO: Crear walletA con el primer saldo inicial
-- TODO: Crear walletB con el segundo saldo inicial
-- TODO: Añadir la cantidad especificada a walletA
-- TODO: Gastar la cantidad especificada de walletB
-- TODO: Imprimir los saldos finales en el formato requerido
-- Formato: "Wallet A: [balance]" y "Wallet B: [balance]"
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
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 formas