What is a metatable?
In Lua, you can hold a whole bundle of information about something in a table, which gives you a convenient "handle" to that information - be that information in the form of values, or behaviours (i.e. conventional variable of code). This is illustrated in earlier articles on
Lua Tables and on
Using Lua tables as objects.
Let's look a stage further. As well as unique pieces of information associated with a particular table / object, you'll want to have common members - pieces of code that run on every table of a certain type (in OO terminology, that's methods that can be run on every member of a class). And this is where
Lua Metatables come in.
A
metatable is itself a table that contains variables and code. It can be linked into / called up from any other table (a parent table, if you like) by using the
setmetatable function. And once that metatable has been set, references made to members that do not exist in the main (parent) table will be passed on to the metatable. This isn't actually a one-to-one mapping - making it a bit harder for me to explain, but much more flexible when I come to use it.
Let's take a look at the standard behaviour of a table:
function newtrain(length) -- set up objectish table
local newone = {}
newone.cars = length
return newone
end
southampton = newtrain(2)
cheltenham = newtrain(3)
print (southampton, cheltenham) -- just prints address
And here's the output:
munchkin:lm12 grahamellis$ lua kitten
table: 0x100106bb0 table: 0x100106c20
munchkin:lm12 grahamellis$
Sample code -
[here]
How do I create a Metatable?
Let's now say that I want ALL the tables created by the
newtrain function to print out nicely, and I also want the abiity to define how to add such table togethers. Rather than define all the extra functinallity lots of times, in Lua I can define a
metabable and then say (in a single call for each of my parent tables) that the train tables all behave in the way defined in my metatable. Let's take a look at how that works:
Firstly, I'll create a table (just an ordinary table) which I'm going to use for my additional functionallity.
demo_metatable = {}
I'll then add some code that's to be shared to that table:
function demo_metatable.__add(this, that)
local newone = {}
newone.cars = this.cars + that.cars
setmetatable(newone, demo_metatable) -- so that we can piggyback additions
return newone
end
function demo_metatable.___tostring(this)
return "A train of " .. this.cars .. " carriages"
end
And finally I'll call up that table in my newtrain function as its metatable
function newtrain(length)
local newone = {}
newone.cars = length
setmetatable(newone, demo_metatable) -- so that we add them
return newone
end
How do I use a Metatable?
Any tables that I now create via the
newtrain function will be "tuned" with the features of the metatable called
demo_metatable ... adding together two tables (using the + operator) has been defined as producing a new table with "cars" members added, and I've also defined how to print such tables.
So I can now write some code to use these functions and the metatable:
southampton = newtrain(2)
cheltenham = newtrain(3)
service = southampton + cheltenham
print (southampton, cheltenham, service)
and the behaviour is modified by the __add function so we don't get:
lua: tabby:27: attempt to perform arithmetic on global 'southampton' (a table value)
stack traceback:
tabby:27: in main chunk
[C]: ?
munchkin:lm12 grahamellis$
but rather an addition is performed, and our printouts saying:
table: 0x100106c20
are replaced by the output from
__tostring:
munchkin:lm12 grahamellis$ lua tabby
A train of 2 carriages A train of 3 carriages A train of 5 carriages
munchkin:lm12 grahamellis$
Sample code
[here]
Adding elements of other names to a metatable
What if I want to add another name of my own choice to every table of a certain type? I can do it, but
not directly by adding that name to the metatable. Instead, I have to provide a function called
__index in the metatable, which can then branch out and act as appropriate.
So if i want this to work:
for _,v in pairs(options) do
print (v, v:getlength(), v.bums, v.capacity, v.earlobes)
end
I might add the following to add the required extra definitions to the metatable:
function demo_metatable.__index(whichmaintable,whatcalled)
if (whatcalled == "getlength") then return demo_metatable.glen end
if (whatcalled == "bums") then return whichmaintable.cars * 73 end
if (whatcalled == "capacity") then return math.floor(whichmaintable.bums * 1.4) end
return "teabag" -- default
end
function demo_metatable.glen(source)
return (source.cars * 23)
end
Sample code
[here]
(written 2012-05-12, updated 2012-05-13)
Associated topics are indexed as below, or enter http://melksh.am/nnnn for individual articles
U107 - Object Orientation - the Lua way [1692] Towards Object Oriented Programming in Lua - (2008-06-30)
[1699] If you are learning Lua, here are some more examples - (2008-07-06)
[1743] First class functions in Lua lead to powerful OO facilities - (2008-08-07)
[1819] Calling base class constructors - (2008-10-03)
[2318] For Lua Programmers AND for Town Planners - (2009-08-02)
[2359] A fresh example - objects the Lua way - (2009-08-13)
[2455] Lua examples - coroutines, error handling, objects, etc - (2009-10-15)
[2701] Is Lua an Object Oriented language? - (2010-04-01)
[2703] Lua Metatables - (2010-04-02)
[2710] __index and __newindex in Lua - metatable methods - (2010-04-05)
[3142] Private and Public - and things between - (2011-01-22)
[3396] Tables as Objects in Lua - a gentle introduction to data driven programming - (2011-08-17)
[3524] Metaclasses (Python) and Metatables (Lua) - (2011-11-17)
[3683] Weak references in Lua - what are they, and why use them? - (2012-04-04)
[3694] Special __ methods you can use in Lua metatables - (2012-04-12)
[3727] Using Lua tables as objects - (2012-05-11)
[4117] Is Lua an Object Oriented language? - (2013-06-15)
[4248] Metatables, Metamethods, classes and objects in Lua - (2014-03-18)
[4273] Dot or Colon separator between table name and member in Lua - what is the difference? - (2014-05-06)
[4572] Tables with values and code in Lua - looks like an object? - (2015-11-05)
[4573] Classic style OO code - in Lua - (2015-11-05)
[4753] Lua, Tcl, Python, C and C++ courses - at our Melksham HQ or on your site - forward from July 2017 - (2017-07-02)
Some other Articles
QR codes with marketing logos embeddedMore hazards of modern lifeTen more visitors to your premises every day?Now Open - A Museum for Melksham. Come in and see us.What is a metatable? How do I set one up? How do I use them? LuaThen and now pictures of Melksham - on show through the summerThe future needs for rail services to Melksham - change needed; current service an insultPress Release - Museum to explore the story of MelkshamLua Tables