Confused with metatables

Hello :smiley:

So I’ve been learning about metatables and how to use OOP in Roblox module scripts. I do understand them, however, I’ve seen many different ways of doing it and I wonder if there is any difference from them. I’ve been trying to google it and understand, but with no luck and I wonder how is the best way to utilize metatables in Lua? I’ve stated some of the different methods below.

Module 1

local module = {}

function module.new()

    local self = {}

    setmetatable(self, { __index = module })

end

return module

Module 2

local module = {}

module.__index = module

function module.new()

    setmetatable({}, module)

end

return module

Module 3

local module = {}

function module.new()

    setmetatable({}, self)

    self.__index = self

end

return module

From what I’ve learned, self is a special variable that refer to the current instance of the object, but as you can see in Module 1 and Module 3, self is used differently. In Module 3, you set self to be the metatable for the object, whilst in Module 1 you set self to be the object that gets a metatable attached (Correct me if I’m wrong, please). This confuses me a lot, and I would appreciate advice on this, what to use and the maybe the difference.

Thank you in advance! :smiley:

3 Likes

Approach one is not preferable because it creates a new metatable when it can reuse the same one.

Approach three doesn’t work at all.

Approach two is the common way to do it. It’s possible to deviate from it certainly but that approach is simple.

Also, you forgot a return on all of the examples, so the above statements assume this return is present.

Lastly, self is just a variable name. What’s peculiar about it is when you define a function using : syntax instead of . syntax it makes self the first parameter automatically. This makes it useful specifically for method definitions that take a state.

Likewise, calling a function with : will automatically pass whatever is to its left as the self parameter.

2 Likes

Oh great, thank you! But about the self, does that mean I can actually name it whatever I want? self isn’t a pre-defined variable?

No, because self is a predefined variable done within the internals of Lua.

Also, here is a more in-depth explanation:

2 Likes

Theoretically you can use anything you want when using the . notation.

function Class.method(this, ...)

end

But it is recommended you use the : notation since it is a method so you can actually get the self implicitly without needing to add it yourself

So lets say I would do this:

local module = {}

module.__index = module

function module.new(someParam)
    local object = {}
    setmetatable(object, module)

    self.someParam = someParam

    return object
end

return module

Would I then have to actually do this:

local module = {}

module.__index = module

function module:new(self, someParam)
    local object = {}
    setmetatable(object, module)

    self.someParam = someParam
    
    return object
end

return module
1 Like

self is automatically passed as the first argument when you use methods, with : syntax.

For example :

  local container = {}

  function container:AddIndex(...)
           for _, v in ipairs({...}) do
           table.insert(self, v) -- essentially table.insert(container, v)
           end
        end
  
  container:AddIndex("str", "str2") 
  -- print(#container) --> 2
  

You can use the __index metamethod so that if an index was not found in a table, Lua will refer to the metamethod; a shared metatable does not share any keys except from the metamethods, for instance

  local Contents = {Name = "Part", Anchored = false}
  print(Contents.Name) --> Part

  local met = setmetatable({},  Contents)
  print(met.Name) --> nil, keys not shared

  Contents.__index = Contents
  print(met.Name) --> prints Part

Edit: Read this reply

2 Likes

No. new is not meant to be a method but rather a constructor.

2 Likes

Metatables kind of confuse me, I usually use LUNA to do my OOP classes:

2 Likes

Luna isn’t perfect. I wrote many years ago, before I had the understanding of Lua that I do now. I would like to rewrite it, and preserve the syntax, but also reduce the complexity between public, private, and static variables.

1 Like

Random metatables comment:
Tables can be their own metatables, and in fact this is often done on Roblox specifically, because when
marshalling tables, the metatable is not sent.

2 Likes