Using metatables to create new objects of "classes"

Hi, so I’m not entirely sure if my understanding of what metatables/metamethods is correct, but would it be possible to create a method on a table object, to basically be the “constructor” of the object, so when I call that it’ll return a new table object with all the methods of the “class.”

Some pseudocode:

local class = {}

function class.new()
--return new instance of class object with base methods and fields
end

function class:Init(x, y)
self.x = x
self.y = y
end

local class_A = class.new()
class_A:Init(45, 80)
local class_B = class.new()
class_B:Init(99, 4)

If clarification is needed please let me know, thanks!

2 Likes

You can achieve this by setting a new table’s __index to class like so:

-- Your class module

local Class = {}
Class.__index = Class -- Set __index to itself so we can apply Class to a new table as a metatable

function Class.new(x, y)
	return setmetatable({x = x, y = y}, Class) -- Set the metatable to Class which has __index pointing to itself which allows you to index values in the new table as well as the original Class table
end

function Class:Method() -- Colon, instead of periods, passes self (the table the method was called on) as the first argument for you without the need to put it in the parameters
	print(self.x, self.y) 
end

-- New script 

local NewClass = Class.new(3, 6)

NewClass:Method()

-- Output: 3 6
4 Likes

What any constructor function does is, create an empty table, because objects in oop are most commonly expressed as tables, then put properties in that empty table, specified along with the constructor’s parameter (Vector3.new(x, y, z), here for example I mean the x and the y and the z, which are technically a property of vector3) represented as keys inside of the empty table. Then for the methods, they aren’t created in the empty table, that’s kind of inefficient, instead using __index the methods can be created inside of the class table which is the class, and can be indexed from that empty table without actually having it inside of the empty table.

local class = {__index = {}} --all methods would be stored inside of this table, the __index one

function class.new(x, y) --the object will have two properties, and x and y coordinates
    local object = {} --let's just say this is our object, the empty table that we're gonna fill
    setmetatable(object, class) --setting the object's metatable, so if a method is called upon it, it will check if the class has that method

    object.X = x
    object.Y = y

    return object --return the object, otherwise just a table
end

local obj = class.new(2,5) --an object, represented as a table

And remember that for methods they have to be inside of __index’s table

function class.__index:Init(x, y)
    self.x = x
    self.y = y
end

And a very good point is, it seems that you create the object first, without any properties, then set the properties using :Init(), so the code would be something like this

local class = {}

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

    return object
end

function class:Init(x, y)
self.x = x
self.y = y
end

local class_A = class.new()
class_A:Init(45, 80)
local class_B = class.new()
class_B:Init(99, 4)

Here is a really good article, read the first part of it to understand more about oop.

10 Likes