Formatting Strings
Part of the Object Oriented Programming section of Coddy's Lua journey — lesson 16 of 70.
When you print an object directly, Lua shows something unhelpful like table: 0x55a...—just a memory address. The __tostring metamethod lets you define exactly what string represents your object when it's printed or converted to text.
In the class pattern, you add __tostring as a function in your class table. Since the class itself serves as the metatable for instances, Lua automatically finds and uses this function:
local Player = {}
Player.__index = Player
function Player:new(name, level)
local instance = {}
setmetatable(instance, self)
instance.name = name
instance.level = level
return instance
end
function Player:__tostring()
return "Player: " .. self.name .. " (Level " .. self.level .. ")"
endNow when you print a Player instance, Lua calls your __tostring method automatically:
local hero = Player:new("Luna", 5)
print(hero) -- Output: Player: Luna (Level 5)Notice that __tostring uses the colon syntax and receives self, giving you access to all instance data. The function must return a string—you can format it however makes sense for your object, combining any attributes into a readable representation.
Challenge
EasyLet's build a Book class that knows how to introduce itself! When you print a book directly, Lua will display a nicely formatted string instead of a cryptic memory address—all thanks to the __tostring metamethod.
You'll organize your code across two files:
Book.lua: Define yourBookclass with the standard prototype pattern. Each book should store atitleand anauthor. Include a:new(title, author)constructor and implement the__tostringmetamethod so that printing a book displays its information in a readable format.main.lua: Require your Book module, create book instances, and print them directly to see your custom string formatting in action.
Your __tostring method should return a string in this exact format:
"[title]" by [author]Notice the title is wrapped in double quotes within the output string.
You will receive four inputs:
- Title of the first book
- Author of the first book
- Title of the second book
- Author of the second book
In your main file, create two books using the provided inputs and print each book directly (not by calling a method—just print(book)). Each book should appear on its own line.
For example, if the inputs are The Hobbit, J.R.R. Tolkien, 1984, and George Orwell, the output should be:
"The Hobbit" by J.R.R. Tolkien
"1984" by George OrwellRemember that __tostring must return a string, and since your class table serves as the metatable for instances, Lua will automatically find and use your __tostring function when you print a book.
Cheat sheet
The __tostring metamethod defines how an object is represented as a string when printed or converted to text.
Without __tostring, printing an object shows only its memory address:
print(someObject) -- Output: table: 0x55a...Add __tostring as a method in your class to customize the string representation:
local Player = {}
Player.__index = Player
function Player:new(name, level)
local instance = {}
setmetatable(instance, self)
instance.name = name
instance.level = level
return instance
end
function Player:__tostring()
return "Player: " .. self.name .. " (Level " .. self.level .. ")"
endWhen you print an instance, Lua automatically calls __tostring:
local hero = Player:new("Luna", 5)
print(hero) -- Output: Player: Luna (Level 5)Key points:
- Use colon syntax (
:) so the method receivesself - Must return a string
- Access instance data through
self - Since the class table serves as the metatable, Lua finds
__tostringautomatically
Try it yourself
-- Require the Book module
local Book = require('Book')
-- Read inputs
local title1 = io.read()
local author1 = io.read()
local title2 = io.read()
local author2 = io.read()
-- TODO: Create two book instances using Book:new()
-- TODO: Print each book directly (just use print(book))
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1The 'Self' Concept
Tables with FunctionsExplicit 'self'The Colon SyntaxDot vs ColonRecap - Moving Point4Project: Digital Bank
Project SetupDeposit Method7Polymorphism & Overriding
Overriding MethodsCalling Parent MethodsDuck TypingCommon InterfaceChecking TypeRecap - Employee Roles10Project: Shape Manager
Project SetupRectangle Class2Class Prototype Pattern
The Prototype ConceptLinking with __indexThe :new() ConstructorInitializing AttributesIndependent InstancesRecap - Car Factory5Operator Overloading in OOP
Adding ObjectsSubtracting ObjectsConcatenating ObjectsComparing Objects (<, >)Recap - Wallet Math8Encapsulation
Naming ConventionsClosures for PrivacyAccess via ClosuresRead-Only TablesValidation LogicRecap - Secure Vault11Design Patterns (Lite)
Factory FunctionsSingleton TableIterator PatternObserver (Listener)Recap - Logger Factory3Object State and Behavior
Instance VariablesGetter MethodsSetter MethodsCalculated PropertiesFormatting StringsEquality ChecksRecap - Student Grade6Inheritance Basics
The Inheritance SetupInheriting MethodsExtending the ConstructorAdding Child MethodsShared vs UniqueRecap - Shape Hierarchy