Concatenar objetos
Parte de la sección Object Oriented Programming del Journey de Lua de Coddy — lección 28 de 70.
El operador .. en Lua concatena cadenas, ¿pero qué pasa si quieres combinar un objeto con una cadena? El metamétodo __concat te permite definir exactamente cómo debería funcionar esto.
Cuando Lua encuentra a .. b y un operando tiene un metamétodo __concat, llama a esa función con ambos valores. Esto es útil cuando quieres que los objetos se integren de forma natural en expresiones de cadena.
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
endObserva que la función comprueba qué operando es la cadena. Dado que .. se puede usar como "Hello " .. obj o obj .. "!", tu metamétodo debería manejar ambos casos.
local person = Name:new("Ada", "Lovelace")
print("Dr. " .. person) -- Salida: Dr. Ada Lovelace
print(person .. " PhD") -- Salida: Ada Lovelace PhDAl igual que otros metamétodos de operador, __concat utiliza la sintaxis de punto y recibe ambos operandos como argumentos. La diferencia clave con respecto a los metamétodos aritméticos es que normalmente se trabaja con tipos mixtos: su objeto y una cadena.
Desafío
FácilVamos a construir una clase Title que pueda integrarse de forma natural en expresiones de cadena utilizando el operador ... Esto es útil cuando deseas combinar objetos con cadenas de una manera legible e intuitiva, como al añadir honoríficos o sufijos al título de una persona.
Organizarás tu código en dos archivos:
Title.lua: Define tu clase Title con un campotextque almacene la cadena del título. Incluye un constructor:new(text)e implementa el metamétodo__concat. Tu metamétodo debe manejar ambos casos: cuando una cadena va antes del objeto ("prefix" .. obj) y cuando una cadena va después (obj .. "suffix"). El resultado debe combinar la cadena con el texto del título de manera apropiada.main.lua: Requiere tu módulo Title, crea una instancia de title y demuestra la concatenación desde ambas direcciones.
Recibirás tres entradas:
- El texto del título (por ejemplo, "Engineer")
- Una cadena de prefijo para colocar antes del título (por ejemplo, "Senior ")
- Una cadena de sufijo para colocar después del título (por ejemplo, " III")
En tu archivo principal, crea un Title con el texto dado. Luego realiza dos concatenaciones e imprime cada resultado en una línea separada:
- Concatena la cadena de prefijo con el objeto title
- Concatena el objeto title con la cadena de sufijo
Por ejemplo, si las entradas son Engineer, Senior , y III, la salida debería ser:
Senior Engineer
Engineer IIILa primera línea muestra el prefijo combinado con el título, y la segunda línea muestra el título combinado con el sufijo. ¡Tu metamétodo __concat hace posible esta combinación natural de cadenas!
Hoja de referencia
El metamétodo __concat te permite definir un comportamiento personalizado para el operador de concatenación .. cuando trabajas con objetos.
Cuando Lua encuentra a .. b y uno de los operandos tiene un metamétodo __concat, llama a esa función con ambos valores.
Implementación 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
endManejo de ambos órdenes de operandos
Dado que .. se puede usar como "string" .. obj o obj .. "string", tu metamétodo debe verificar qué operando es la cadena y manejar ambos 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
endEjemplo de uso
local person = Name:new("Ada", "Lovelace")
print("Dr. " .. person) -- Salida: Dr. Ada Lovelace
print(person .. " PhD") -- Salida: Ada Lovelace PhDAl igual que otros metamétodos de operador, __concat utiliza la sintaxis de punto y recibe ambos operandos como argumentos.
Pruébalo tú mismo
-- Leer entradas
local titleText = io.read()
local prefix = io.read()
local suffix = io.read()
-- Requerir el módulo Title
local Title = require('Title')
-- TODO: Crear una instancia de Title con el titleText dado
-- TODO: Concatenar el prefijo con el objeto title e imprimir el resultado
-- TODO: Concatenar el objeto title con el sufijo e imprimir el resultado
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Object Oriented Programming
1El concepto de 'self'
Tablas con funciones'self' explícitoLa sintaxis de dos puntosPunto vs. dos puntosResumen - Punto en movimiento4Proyecto: Banco Digital
Configuración del proyectoMétodo de depósito2Patrón de prototipo de clase
El concepto de prototipoVinculación con __indexEl constructor :new()Inicialización de atributosInstancias independientesResumen - Fábrica de coches5Sobrecarga de operadores en POO
Sumar objetosRestar objetosConcatenar objetosComparar objetos (<, >)Resumen - Matemáticas de la billetera8Encapsulamiento
Convenciones de nomenclaturaClosures para privacidadAcceso mediante ClosuresTablas de solo lecturaLógica de validaciónResumen - Bóveda segura11Patrones de diseño (Lite)
Funciones FactoryTabla SingletonPatrón IteradorObserver (Listener)Resumen - Logger Factory3Estado y Comportamiento de los Objetos
Variables de InstanciaMétodos GetterMétodos SetterPropiedades CalculadasFormateo de StringsComprobaciones de IgualdadResumen - Calificación del Estudiante6Fundamentos de la herencia
Configuración de la herenciaHerencia de métodosExtender el constructorAñadir métodos hijosCompartido vs. ÚnicoResumen: Jerarquía de formas