Concatenando Objetos
Parte da seção Object Oriented Programming do Journey de Lua da Coddy — lição 28 de 70.
O operador .. em Lua concatena strings, mas e se você quiser combinar um objeto com uma string? O metamétodo __concat permite que você defina exatamente como isso deve funcionar.
Quando o Lua encontra a .. b e um operando possui um metamétodo __concat, ele chama essa função com ambos os valores. Isso é útil quando você deseja que objetos se misturem naturalmente em expressões de string.
local Name = {}
Name.__index = Name
function Name:new(first, last)
local obj = {first = first, last = last}
setmetatable(obj, Name)
return obj
end
function Name.__concat(a, b)
if type(a) == "string" then
return a .. b.first .. " " .. b.last
else
return a.first .. " " .. a.last .. b
end
endObserve que a função verifica qual operando é a string. Como .. pode ser usado como "Hello " .. obj ou obj .. "!", seu metamétodo deve lidar com ambos os casos.
local person = Name:new("Ada", "Lovelace")
print("Dr. " .. person) -- Saída: Dr. Ada Lovelace
print(person .. " PhD") -- Saída: Ada Lovelace PhDComo outros metamétodos de operador, __concat usa a sintaxe de ponto e recebe ambos os operandos como argumentos. A principal diferença em relação aos metamétodos aritméticos é que você geralmente está trabalhando com tipos mistos — seu objeto e uma string.
Desafio
FácilVamos construir uma classe Title que possa se misturar naturalmente em expressões de string usando o operador ... Isso é útil quando você deseja combinar objetos com strings de uma maneira legível e intuitiva — como adicionar honoríficos ou sufixos ao título de uma pessoa.
Você organizará seu código em dois arquivos:
Title.lua: Defina sua classe Title com um campotextque armazena a string do título. Inclua um construtor:new(text)e implemente o metamétodo__concat. Seu metamétodo deve lidar com ambos os casos: quando uma string vem antes do objeto ("prefix" .. obj) e quando uma string vem depois (obj .. "suffix"). O resultado deve combinar a string com o texto do título apropriadamente.main.lua: Importe seu módulo Title, crie uma instância de título e demonstre a concatenação de ambas as direções.
Você receberá três entradas:
- O texto do título (ex: "Engineer")
- Uma string de prefixo para colocar antes do título (ex: "Senior ")
- Uma string de sufixo para colocar depois do título (ex: " III")
No seu arquivo principal, crie um Title com o texto fornecido. Em seguida, realize duas concatenações e imprima cada resultado em uma linha separada:
- Concatene a string de prefixo com o objeto title
- Concatene o objeto title com a string de sufixo
Por exemplo, se as entradas forem Engineer, Senior , e III, a saída deve ser:
Senior Engineer
Engineer IIIA primeira linha mostra o prefixo combinado com o título, e a segunda linha mostra o título combinado com o sufixo. Seu metamétodo __concat torna possível essa mistura natural de strings!
Folha de consulta
O metamétodo __concat permite que você defina um comportamento personalizado para o operador de concatenação .. ao trabalhar com objetos.
Quando o Lua encontra a .. b e um dos operandos possui um metamétodo __concat, ele chama essa função com ambos os valores.
Implementação Básica
local MyClass = {}
MyClass.__index = MyClass
function MyClass:new(value)
local obj = {value = value}
setmetatable(obj, MyClass)
return obj
end
function MyClass.__concat(a, b)
if type(a) == "string" then
return a .. b.value
else
return a.value .. b
end
endLidando com Ambas as Ordens de Operandos
Como o .. pode ser usado como "string" .. obj ou obj .. "string", seu metamétodo deve verificar qual operando é a string e tratar ambos os casos:
function Name.__concat(a, b)
if type(a) == "string" then
return a .. b.first .. " " .. b.last
else
return a.first .. " " .. a.last .. b
end
endExemplo de Uso
local person = Name:new("Ada", "Lovelace")
print("Dr. " .. person) -- Output: Dr. Ada Lovelace
print(person .. " PhD") -- Output: Ada Lovelace PhDAssim como outros metamétodos de operador, o __concat utiliza a sintaxe de ponto e recebe ambos os operandos como argumentos.
Experimente você mesmo
-- Ler entradas
local titleText = io.read()
local prefix = io.read()
local suffix = io.read()
-- Requerer o módulo Title
local Title = require('Title')
-- TODO: Criar uma instância de Title com o titleText fornecido
-- TODO: Concatenar o prefixo com o objeto title e imprimir o resultado
-- TODO: Concatenar o objeto title com o sufixo e imprimir o resultado
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