Variáveis de Instância
Parte da seção Programação Orientada a Objetos do Journey de Lua da Coddy. Lição 12 de 70.
Boas-vindas a um novo capítulo focado em como os objetos gerenciam seus dados internos. Você aprendeu a criar classes e instâncias; agora é hora de explorar como cada instância armazena e gerencia seu próprio estado exclusivo.
Variáveis de instância são campos que pertencem exclusivamente a um único objeto. Quando você atribui um valor a self.something dentro de um método ou construtor, esses dados existem apenas nessa instância específica. Outros objetos da mesma classe têm suas próprias cópias separadas.
Isso se torna especialmente importante ao armazenar dados complexos, como tabelas. Considere um sistema de inventário em que cada personagem carrega itens diferentes:
local Inventory = {}
Inventory.__index = Inventory
function Inventory:new()
local instance = {}
setmetatable(instance, self)
instance.items = {} -- Cada instância recebe sua própria tabela vazia
return instance
end
function Inventory:addItem(item)
table.insert(self.items, item)
endA linha principal é instance.items = {}. Ao criar uma nova tabela vazia dentro do construtor, cada objeto de inventário recebe sua própria lista distinta. Se, em vez disso, você definisse items na própria tabela da classe, todas as instâncias acidentalmente compartilhariam a mesma tabela: adicionar uma espada a um personagem daria essa espada a todos!
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- Saída: 1
print(#bag2.items) -- Saída: 1Cada inventário mantém sua própria coleção. Esse padrão se aplica sempre que uma instância precisa acompanhar dados que mudam de forma independente: listas, contadores ou qualquer estado mutável exclusivo desse objeto.
Desafio
FácilVamos criar um sistema de ShoppingCart em que cada carrinho mantém sua própria lista separada de produtos. Isso demonstrará como as variáveis de instância mantêm os dados isolados entre os objetos: adicionar itens a um carrinho não afetará outro!
Você organizará seu código em dois arquivos:
ShoppingCart.lua: defina sua classeShoppingCart, em que cada instância tem sua própria tabelaproducts. Inclua:- Um construtor
:new()que inicializa uma lista de produtos vazia para cada carrinho - Um método
:addProduct(productName)que adiciona um produto à lista deste carrinho - Um método
:listProducts()que imprime cada produto em uma linha separada
- Um construtor
main.lua: importe seu módulo ShoppingCart e crie dois carrinhos separados. Adicione produtos diferentes a cada carrinho para provar que eles mantêm inventários independentes.
Você receberá quatro entradas:
- Primeiro produto a ser adicionado ao carrinho A
- Segundo produto a ser adicionado ao carrinho A
- Primeiro produto a ser adicionado ao carrinho B
- Segundo produto a ser adicionado ao carrinho B
No seu arquivo principal:
- Crie dois carrinhos de compras:
cartAecartB - Adicione os dois primeiros produtos a
cartA - Adicione os dois últimos produtos a
cartB - Imprima
Cart A:e depois liste os produtos do carrinho A - Imprima
Cart B:e depois liste os produtos do carrinho B
Por exemplo, se as entradas forem Apple, Bread, Milk e Eggs, a saída deverá ser:
Cart A:
Apple
Bread
Cart B:
Milk
EggsLembre-se: o segredo é inicializar products como uma nova tabela vazia dentro do construtor. Isso garante que cada instância do carrinho receba sua própria lista separada, em vez de compartilhar uma tabela entre todos os carrinhos.
Experimente você mesmo
-- Requer o módulo ShoppingCart
local ShoppingCart = require('ShoppingCart')
-- Lê as entradas
local product1 = io.read()
local product2 = io.read()
local product3 = io.read()
local product4 = io.read()
-- TODO: Crie dois carrinhos de compras: cartA e cartB
-- TODO: Adicione product1 e product2 ao cartA
-- TODO: Adicione product3 e product4 ao cartB
-- TODO: Imprima "Cart A:" e então liste os produtos de cartA
-- TODO: Imprima "Cart B:" e então liste os produtos de cartB
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
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ânguloClasse CírculoMétodo PerímetroColeção de FormasÁrea TotalFiltrar Formas2Padrã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 FormasPratique por conta própria: Compilador de Lua online