Lua: Methods
Lua |
---|
Basics |
Intermediate |
Advanced |
|
XLua |
Add to this template |
Methods are functions that are used by an object. 'Object' doesn't necessarily mean a game object, but instead some data structure that contains a set of variables and functions (the methods). Of course, the data structures we will be using are tables (usually).
Lua's methods have a special syntax; you don't need to use this syntax, but it's cleaner and easier than the alternative. Called colon syntax, it of course uses a colon instead of a dot:
-- regular function
table.function_call()
-- method
table:method_call()
Basically, by using the colon, you insert the data structure immediately left of the colon as a hidden first parameter. Therefore, these two calls are equivalent:
table.method(table, other_param)
table:method(other_param)
When you're writing the source code, however, that first parameter will generally be something else. It's just a regular variable, so it doesn't necessarily need to have the same name as the data structure calling the method (you should avoid this, in fact). You'll often see this variable named self, as this is the variable name Lua uses if the method definition does not explicitly state another name for its first parameter.
Table Methods
In order to use methods for any given table, we need to give it a metatable. Because we don't want the methods to actually "pollute" this table, we will have them stored in a separate table called methods. So our code should start out like this:
methods = { }
function newTable(t_data)
return setmetatable(t_data, methods)
end
Now we need to write a method for the methods table. A useful one will return the length of the entire table, including non-numeric keys, which are normally ignored by the length operator. So our methods table will look like:
methods = {
length = function (self)
local l = 0
for k in pairs(self) do
if string.sub(k, 1, 2) ~= "__" then
l = l + 1
end
end
return l
end,
}
methods.__index = methods
This is a similar table iteration as the __add metamethod from the Metatables tutorial. However, instead of adding the values at two tables' indexes, we're just incrementing a variable to use as our length. Note how we are using string.sub to exclude key names starting with '__'; we don't want metamethods to be counted in the length! We also define methods' __index metamethod to point to itself, so Lua knows this is the table that has the methods we need. We're actually done now, so we should try testing it:
methods = {
length = function (self)
local l = 0
for k in pairs(self) do
if string.sub(k, 1, 2) ~= "__" then
l = l + 1
end
end
return l
end,
}
methods.__index = methods
function newTable(t_data)
return setmetatable(t_data, methods)
end
test = newTable {1, 2, 3, a = 4, b = 5, c = 6}
print(test:length()) -- prints 6
print(test.length(test)) -- prints 6 (longhand for above)
print(methods.length(test)) -- prints 6 (the "real" call, bypassing the metatable lookup)
print(#test) -- prints 3!
print(newTable {1,2,3, four = 4}:length()) -- believe it or not, this works too (prints 4)
Methods are a nice way to make your code not only cleaner, but also more modular. Instead of having to repeat the same code over and over for multiple tables, you can just __index them to the same methods table and they can all take advantage of methods.