Instâncias Independentes
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 10 de 70.
Um aspecto crucial da programação orientada a objetos é que cada instância mantém seu próprio estado separado. Quando você cria dois objetos a partir da mesma classe, eles são completamente independentes — alterar um não afeta o outro.
Considere este exemplo:
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: 5Embora ambos os contadores venham da mesma classe Counter, incrementar counterA não tem efeito sobre counterB. Cada objeto tem seu próprio campo value armazenado em sua própria tabela de instância.
Essa independência é o que torna os objetos úteis. Você pode criar dezenas de jogadores em um jogo, cada um rastreando sua própria vida e pontuação. Você pode gerenciar várias contas bancárias, cada uma com um saldo diferente.
A classe define a estrutura e o comportamento, mas cada instância vive sua própria vida com seus próprios dados.
Desafio
FácilVamos provar que objetos da mesma classe realmente vivem vidas independentes! Você construirá uma classe Wallet e criará duas instâncias de carteira separadas, depois as modificará independentemente para demonstrar que as alterações em uma não afetam a outra.
Você organizará seu código em dois arquivos:
Wallet.lua: Defina sua classeWalletcom o padrão de construtor padrão. Cada carteira deve rastrear seu própriobalance. Inclua:- Um construtor
:new(startingBalance)que inicializa a carteira com o valor fornecido - Um método
:add(amount)que aumenta o saldo - Um método
:spend(amount)que diminui o saldo
- Um construtor
main.lua: Requeira seu módulo Wallet e crie duas instâncias de carteira separadas. Realize operações diferentes em cada uma para mostrar que elas mantêm estados independentes.
Você receberá quatro entradas:
- Saldo inicial para a carteira A
- Saldo inicial para a carteira B
- Valor a ser adicionado à carteira A
- Valor a ser gasto da carteira B
No seu arquivo principal:
- Crie
walletAcom o primeiro saldo inicial - Crie
walletBcom o segundo saldo inicial - Adicione o valor especificado a
walletA - Gaste o valor especificado de
walletB - Imprima ambos os saldos em linhas separadas
Imprima os saldos finais neste formato exato:
Wallet A: [balance]
Wallet B: [balance]Por exemplo, se as entradas forem 100, 50, 25 e 10, a saída deve ser:
Wallet A: 125
Wallet B: 40Observe como adicionar à carteira A não altera a carteira B, e gastar da carteira B não afeta a carteira A — cada instância mantém seu próprio saldo separado.
Folha de consulta
Cada instância de uma classe mantém seu próprio estado separado. Criar múltiplos objetos a partir da mesma classe resulta em instâncias completamente independentes — modificar uma não afeta as outras.
Exemplo demonstrando a independência de instâncias:
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
-- Criar dois contadores separados
local counterA = Counter:new(10)
local counterB = Counter:new(5)
counterA:increment()
counterA:increment()
print(counterA.value) -- Saída: 12
print(counterB.value) -- Saída: 5Cada objeto possui sua própria tabela de instância armazenando seus próprios dados. A classe define a estrutura e o comportamento, mas cada instância mantém um estado independente.
Experimente você mesmo
-- Requer o módulo Wallet
local Wallet = require('Wallet')
-- Lê as entradas
local startingA = tonumber(io.read())
local startingB = tonumber(io.read())
local addAmount = tonumber(io.read())
local spendAmount = tonumber(io.read())
-- TODO: Criar walletA com o primeiro saldo inicial
-- TODO: Criar walletB com o segundo saldo inicial
-- TODO: Adicionar a quantia especificada à walletA
-- TODO: Gastar a quantia especificada da walletB
-- TODO: Imprimir os saldos finais no formato exigido
-- Formato: "Wallet A: [balance]" e "Wallet B: [balance]"
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Object Oriented Programming
1O Conceito 'Self'
Tabelas com Funções'self' ExplícitoA Sintaxe de Dois-pontosPonto vs Dois-pontosRecapitulação - Movendo o Ponto4Projeto: Banco Digital
Configuração do ProjetoMétodo de Depósito7Polimorfismo e Sobrescrita
Sobrescrita de MétodosChamando Métodos da Classe PaiDuck TypingInterface ComumVerificando o TipoRecapitulação - Papéis de Funcionários10Projeto: Gerenciador de Formas
Configuração do ProjetoClasse Retângulo2Padrão de Protótipo de Classe
O Conceito de ProtótipoVinculando com __indexO Construtor :new()Inicializando AtributosInstâncias IndependentesRecapitulação - Fábrica de Carros5Sobrecarga de Operadores em POO
Somando ObjetosSubtraindo ObjetosConcatenando ObjetosComparando Objetos (<, >)Recapitulação - Matemática de Carteira8Encapsulamento
Convenções de NomenclaturaClosures para PrivacidadeAcesso via ClosuresTabelas Somente LeituraLógica de ValidaçãoRecapitulação - Cofre Seguro11Padrões de Projeto (Lite)
Funções FactoryTabela SingletonPadrão IteratorObserver (Listener)Recapitulação - Logger Factory3Estado e Comportamento do Objeto
Variáveis de InstânciaMétodos GetterMétodos SetterPropriedades CalculadasFormatação de StringsVerificações de IgualdadeRecapitulação - Nota do Aluno6Fundamentos de Herança
Configurando a HerançaHerdando MétodosEstendendo o ConstrutorAdicionando Métodos FilhosCompartilhado vs ÚnicoRecapitulação - Hierarquia de Formas