Returning a ClassReference from a Metatable value

Given a class utilizing a metatable. And a table to find each class instance created.

local myClassList = {} -- A table that holds a reference to each instantiated class
local myClassName = {} -- The class definition
myClassName.name = "defaultMyClass" -- A property holding a string that represents the classes name 
myClassName.list = {} -- a property of the class

local myClassName_MT = {__index = myClassName} -- A metatable that index missing values from myClass

When instantiating an instance of this class and adding the reference to the table that holds each instantiated class.

function module.New(name, param1, param2, param3)
  local self = setmetatable({}, myClassName_MT)
  self.name = name
  table.insert(myClassList, self)
  return self
end

If you then added a method to the class that populates the list associated with the class using image label instances.

function myClassName:Populate()
  for i=1, 20 do
    table.insert(self.list, Instance.new("ImageLabel"))
  end
end

Now that the list is populated in the class if you were to find a particular class from a particular image label using values from the “list” property.

function module:GetClassFromImageLabel(x)
  for _, myClass in ipairs(myClassList) do
    for i,v in ipairs(myClass.list) do
      print(myClass.name)
      if v == x then -- if the imageLabel we provided as an argument is the same as the imageLabel in the class
        return myClass -- return the class that contains the imageLabel
      end
    end
  end
end

If you then created two instances of this class.

local myClass1 = module.New("mainClass")
myClass1:Populate()

local myClass2 = module.New("differentClass")
myClass2:Populate()

And you then searched for a particular imageLabel; why would the resulting value be both classes?

Full Scripts

-- Module Script
local module = {}
local myClassList = {} -- A table that holds a reference to each instantiated class
local myClassName = {} -- The class definition
myClassName.name = "defaultMyClass" -- A property holding a string that represents the classes name
myClassName.list = {} -- a property of the class

-- Metatable
local myClassName_MT = {__index = myClassName} -- A metatable that index missing values from myClass

-- Methods
function myClassName:Populate()
  for i=1, 20 do
    table.insert(self.list, Instance.new("ImageLabel"))
  end
end

function module.New(name, param1, param2, param3)
  local self = setmetatable({}, myClassName_MT)
  self.name = name

  table.insert(myClassList, self)
  return self
end

function module:GetClassFromImageLabel(x)
  for _, myClass in ipairs(myClassList) do
    for i,v in ipairs(myClass.list) do
     print(myClass.name)
      if v == x then -- if the imageLabel we provided as an argument is the same as the imageLabel in the class
        return myClass -- return the class that contains the imageLabel
      end
    end
  end
end

return module

– Script using ModuleScript housing the class

local myClassModule = require(script.myClassModule)

local myClass1 = module.New("mainClass")
myClass1:Populate()

local myClass2 = module.New("differentClass")
myClass2:Populate()
local someFakeImageLabelThatFitsThisExample = playerGui.imageLabel
local foundClass = myClassModule:GetClassFromImageLabel(someFakeImageLabelThatFitsThisExample)

The issue here is that during this script execution the output log prints “mainClass” and “differentClass” and then returns “differentClass”. Regardless of whether or not the image label is in the list of “mainClass”.

However, if I set self.list = {} during the class construction like below.

function module.New(name, param1, param2, param3)
  local self = setmetatable({}, myClassName_MT)
  self.name = name

  self.list = {}
  table.insert(myClassList, self)
  return self
end

Once I set the property during the construction the correct class is now returned when calling. myClassModule:GetClassFromImageLabel().

  • Why does the metatable behavior cause this to happen?
  • Why isn’t the “list” table of the class instance populated instead when calling myClassName:Populate()