I'd like to create MyClass
class in Lua in a separate file myclass.lua which I can import and use later.
It should be working the following way:
local MyClass = require 'myclass'
tab = {1,2,3}
m = MyClass(tab)
However, following the code in Lua docs I can't make it work and am getting errors attempt to call global 'MyClass' (a table value)
.
The code I have written so far for myclass.lua:
local MyClass = {}
MyClass.__index = MyClass
function MyClass.__init(tab)
self.tab = tab or {}
setmetatable({},MyClass)
return self
end
return MyClass
There is a plethora of examples how to write classes in Lua but I don't think I understand the difference and as a result getting lost in the implementation details. Is there a more or less conventional way to do it?
In Lua, you cannot usually call a table like you would call a function. For example, this code will produce an error of "attempt to call local 't' (a table value)".
There is a way of making this work by using metatables, however.
When you try and call a table as you would a function, Lua first checks to see whether the table has a metatable. If it does, then it tries to call the function in the
__call
property of that metatable. The first argument to the__call
function is the table itself, and subsequent arguments are the arguments that were passed when the table was called as a function. If the table doesn't have a metatable, or the metatable doesn't have a__call
function, then an "attempt to call local 't'" error is raised.Your example code has three problems:
__init
instead of__call
. Lua doesn't have an__init
metamethod.__call
takes different parameters than the ones you are using. The first parameter to the__call
function is the table itself. You can either usefunction MyClass.__call(self, tab)
, or use the colon syntax,function MyClass:__call(tab)
, which implicitly adds theself
parameter for you. These two syntaxes are functionally identical.MyClass
table. While you are setting a metatable for MyClass's objects, that doesn't mean that a metatable is automatically set for MyClass itself.To fix this, you could do something like the following:
This sets MyClass to use itself as a metatable, which is perfectly valid Lua.
The system of metatables is very flexible, and allows you to have just about any class/object scheme you want. For example, if you want, you can do everything inline.
As well as being concise, this also has the advantage that people can't change the class's metamethods if they have access to the class table.