Menu
Coddy logo textTech

Concatenating Objects

Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 28 of 70.

The .. operator in Lua concatenates strings, but what if you want to combine an object with a string? The __concat metamethod lets you define exactly how this should work.

When Lua encounters a .. b and one operand has a __concat metamethod, it calls that function with both values. This is useful when you want objects to blend naturally into string expressions.

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
end

Notice the function checks which operand is the string. Since .. can be used as "Hello " .. obj or obj .. "!", your metamethod should handle both cases.

local person = Name:new("Ada", "Lovelace")

print("Dr. " .. person)      -- Output: Dr. Ada Lovelace
print(person .. " PhD")      -- Output: Ada Lovelace PhD

Like other operator metamethods, __concat uses dot syntax and receives both operands as arguments. The key difference from arithmetic metamethods is that you're typically working with mixed types—your object and a string.

challenge icon

Challenge

Easy

Let's build a Title class that can blend naturally into string expressions using the .. operator. This is useful when you want to combine objects with strings in a readable, intuitive way—like adding honorifics or suffixes to a person's title.

You'll organize your code across two files:

  • Title.lua: Define your Title class with a text field that stores the title string. Include a :new(text) constructor and implement the __concat metamethod. Your metamethod should handle both cases: when a string comes before the object ("prefix" .. obj) and when a string comes after (obj .. "suffix"). The result should combine the string with the title's text appropriately.
  • main.lua: Require your Title module, create a title instance, and demonstrate concatenation from both directions.

You will receive three inputs:

  1. The title text (e.g., "Engineer")
  2. A prefix string to place before the title (e.g., "Senior ")
  3. A suffix string to place after the title (e.g., " III")

In your main file, create a Title with the given text. Then perform two concatenations and print each result on a separate line:

  1. Concatenate the prefix string with the title object
  2. Concatenate the title object with the suffix string

For example, if the inputs are Engineer, Senior , and III, the output should be:

Senior Engineer
Engineer III

The first line shows the prefix combined with the title, and the second line shows the title combined with the suffix. Your __concat metamethod makes this natural string blending possible!

Cheat sheet

The __concat metamethod allows you to define custom behavior for the .. concatenation operator when working with objects.

When Lua encounters a .. b and one operand has a __concat metamethod, it calls that function with both values.

Basic Implementation

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
end

Handling Both Operand Orders

Since .. can be used as "string" .. obj or obj .. "string", your metamethod should check which operand is the string and handle both cases:

function Name.__concat(a, b)
    if type(a) == "string" then
        return a .. b.first .. " " .. b.last
    else
        return a.first .. " " .. a.last .. b
    end
end

Usage Example

local person = Name:new("Ada", "Lovelace")

print("Dr. " .. person)      -- Output: Dr. Ada Lovelace
print(person .. " PhD")      -- Output: Ada Lovelace PhD

Like other operator metamethods, __concat uses dot syntax and receives both operands as arguments.

Try it yourself

-- Read inputs
local titleText = io.read()
local prefix = io.read()
local suffix = io.read()

-- Require the Title module
local Title = require('Title')

-- TODO: Create a Title instance with the given titleText

-- TODO: Concatenate prefix with the title object and print the result

-- TODO: Concatenate the title object with suffix and print the result
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming