Propriedades Calculadas
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 15 de 70.
Getters e setters fornecem acesso a valores armazenados, mas às vezes você precisa de dados que não existem como um campo armazenado — eles precisam ser calculados a partir de outros atributos. Estes são chamados de propriedades calculadas.
Considere um retângulo. Você armazena sua largura e altura, mas a área não é armazenada em lugar nenhum — ela é calculada multiplicando esses dois valores. Em vez de armazenar dados redundantes, você cria um método que calcula e retorna o resultado:
local Rectangle = {}
Rectangle.__index = Rectangle
function Rectangle:new(width, height)
local instance = {}
setmetatable(instance, self)
instance.width = width
instance.height = height
return instance
end
function Rectangle:getArea()
return self.width * self.height
endO método :getArea() não retorna um valor armazenado — ele calcula a área novamente toda vez que você o chama. Esta abordagem tem uma vantagem principal: se a largura ou a altura mudar, a área reflete automaticamente as novas dimensões sem que você precise atualizar nada.
local box = Rectangle:new(5, 3)
print(box:getArea()) -- Saída: 15
box.width = 10
print(box:getArea()) -- Saída: 30Propriedades calculadas mantêm seus objetos consistentes. Em vez de armazenar valores que dependem de outros campos (e correr o risco de que eles fiquem desatualizados), você os calcula sob demanda. Este padrão se aplica a quaisquer dados derivados — perímetros, médias, strings formatadas ou qualquer valor que possa ser determinado a partir de atributos existentes.
Desafio
FácilVamos construir uma classe Box que calcula seu volume sob demanda! Em vez de armazenar o volume como um campo, você criará uma propriedade calculada que o computa a partir das dimensões da caixa sempre que for necessário.
Você organizará seu código em dois arquivos:
Box.lua: Defina sua classeBoxcom o padrão de protótipo padrão. Cada caixa armazena três dimensões:width,heightedepth. Inclua:- Um construtor
:new(width, height, depth)que armazena todas as três dimensões - Um método
:getVolume()que calcula e retorna o volume (width × height × depth) - Um método
:getSurfaceArea()que calcula e retorna a área de superfície total
- Um construtor
main.lua: Requeira seu módulo Box, crie uma instância de box e demonstre como as propriedades calculadas refletem automaticamente as dimensões atuais.
A área de superfície de uma caixa é calculada como: 2 × (width×height + height×depth + width×depth)
Você receberá três entradas representando as dimensões da caixa:
- Largura (Width)
- Altura (Height)
- Profundidade (Depth)
No seu arquivo principal, crie uma caixa com as dimensões fornecidas e, em seguida, imprima duas linhas:
- O volume usando
:getVolume() - A área de superfície usando
:getSurfaceArea()
Por exemplo, se as entradas forem 3, 4 e 5, a saída deve ser:
60
94A beleza das propriedades calculadas é que elas permanecem sempre precisas. Se você alterar posteriormente uma das dimensões da caixa, chamar :getVolume() novamente retornará automaticamente o novo valor correto — sem necessidade de atualizações manuais!
Folha de consulta
Propriedades calculadas são métodos que computam e retornam valores baseados em outros atributos, em vez de armazená-los diretamente. Isso garante a consistência dos dados e elimina a redundância.
Exemplo de uma propriedade calculada para área:
local Rectangle = {}
Rectangle.__index = Rectangle
function Rectangle:new(width, height)
local instance = {}
setmetatable(instance, self)
instance.width = width
instance.height = height
return instance
end
function Rectangle:getArea()
return self.width * self.height
endO método :getArea() calcula a área toda vez que é chamado, refletindo automaticamente qualquer alteração na largura (width) ou altura (height):
local box = Rectangle:new(5, 3)
print(box:getArea()) -- Output: 15
box.width = 10
print(box:getArea()) -- Output: 30Propriedades calculadas são úteis para quaisquer dados derivados, como perímetros, volumes, médias ou strings formatadas que podem ser determinadas a partir de atributos existentes.
Experimente você mesmo
-- Importa o módulo Box
local Box = require('Box')
-- Lê as dimensões de entrada
local width = tonumber(io.read())
local height = tonumber(io.read())
local depth = tonumber(io.read())
-- TODO: Cria uma instância de box com as dimensões fornecidas
-- TODO: Imprime o volume usando :getVolume()
-- TODO: Imprime a área de superfície usando :getSurfaceArea()
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