Variáveis de Instância
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 12 de 70.
Bem-vindo 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 único.
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 residem apenas naquela instância específica. Outros objetos da mesma classe possuem suas próprias cópias separadas.
Isso se torna especialmente importante ao armazenar dados complexos, como tabelas. Considere um sistema de inventário onde 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 a daria 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. Este padrão se aplica sempre que uma instância precisa rastrear dados que mudam de forma independente — listas, contadores ou qualquer estado mutável exclusivo desse objeto.
Desafio
FácilVamos construir um sistema de ShoppingCart onde 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á o outro!
Você organizará seu código em dois arquivos:
ShoppingCart.lua: Defina sua classeShoppingCartonde 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: Requeira 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 para adicionar ao carrinho A
- Segundo produto para adicionar ao carrinho A
- Primeiro produto para adicionar ao carrinho B
- Segundo produto para adicionar ao carrinho B
No seu arquivo principal:
- Crie dois carrinhos de compras:
cartAecartB - Adicione os dois primeiros produtos ao
cartA - Adicione os dois últimos produtos ao
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 deve ser:
Cart A:
Apple
Bread
Cart B:
Milk
EggsLembre-se: a chave é inicializar products como uma nova tabela vazia dentro do construtor. Isso garante que cada instância de carrinho receba sua própria lista separada, em vez de compartilhar uma única tabela entre todos os carrinhos.
Folha de consulta
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 vivem apenas naquela instância específica.
Para criar variáveis de instância, inicialize-as dentro do construtor usando uma nova tabela para cada instância:
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 chave é instance.items = {}—criar uma nova tabela vazia dentro do construtor garante que cada objeto receba seus próprios dados distintos. Se você definisse items na própria tabela da classe, todas as instâncias compartilhariam a mesma tabela.
local bag1 = Inventory:new()
local bag2 = Inventory:new()
bag1:addItem("Sword")
bag2:addItem("Potion")
print(#bag1.items) -- Output: 1
print(#bag2.items) -- Output: 1Cada instância mantém sua própria coleção de forma independente. Este padrão se aplica a qualquer estado mutável exclusivo de um objeto—listas, contadores ou outros dados que mudam por instância.
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: Criar dois carrinhos de compras: cartA e cartB
-- TODO: Adicionar product1 e product2 ao cartA
-- TODO: Adicionar product3 e product4 ao cartB
-- TODO: Imprimir "Cart A:" e depois listar os produtos do cartA
-- TODO: Imprimir "Cart B:" e depois listar os produtos do 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 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