Kousha
Kousha

Reputation: 36219

Confused about Lua constructor argument

I'm following this example OOP in Lua - Creating a class?:

local Class = {}
local Object = {}
Object.__index = Object

function Class.new(arg1)
    print(require('app.utils').asString(arg1))
    print(require('app.utils').asString(getmetatable(arg1)))

    return setmetatable({}, Object)
end
setmetatable(Class, {__call = Class.new})

return Class

I'm just dumping the first argument, and here is what I get

Class.new('123')
-- prints
123
{ ["__index"] = { ["reverse"] = function: builtin#82,["dump"] = function: builtin#85,["match"] = function: builtin#87,["rep"] = function: builtin#81,["len"] = function: 0x07b63050,["upper"] = function: builtin#84,["format"] = function: builtin#91,["find"] = function: builtin#86,["char"] = function: builtin#79,["sub"] = function: builtin#80,["gsub"] = function: builtin#90,["gmatch"] = function: builtin#89,["lower"] = function: builtin#83,["byte"] = function: builtin#78, } , } 


Class:new('123')
{ ["new"] = function: 0x029dcd08, } 
{ ["__call"] = function: 0x029dcd08, } 

What I'm confused about is how the first use cass .new provides the metadata when I do getmetadata(arg1). Why does the argument have a metadata here? Is that because the first argument in Class.new is actually self?

Upvotes: 1

Views: 368

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473926

Why does the argument have a metadata here?

Because you provided an object which has a metatable.

Every object in Lua can have a metatable. This includes strings. The Lua standard string library sets the string library table as the __index metamethod for the string metatable. So it's legal to do ('123'):reverse().

This metatable is shared among all strings (instead of each individual string having its own metatable), which is why the string you provided has a metatable despite you not explicitly setting one. But it is still a legitimate metatable that you can query and act on.

Upvotes: 2

Related Questions