Is there any way to keep an object's metatable?

I’m trying to make two classes, one is Town, and the another is TownPlotManager.
Consider the following three scripts:

-- TownPlotManager code (module)
local TownPlotManager = {}
TownPlotManager.__index = TownPlotManager

function TownPlotManager.new(townPlotManager)
    local self = townPlotManager
    setmetatable(self, TownPlotManager)

    return self
end

function TownPlotManager:RenderPlots()
    -- more code here
end

 --defaultTownDataModule (module)
local Town = require(script.Town)
local TownPlotManager = require(script.TownPlotManager) --
return Town.new{
    TownPlotManager = TownPlotManager.new() -- args here
}

--TownDataLoader (script)
local defaultTownDataModule = require(game.ServerScriptService.defaultTownDataModule)
local userTownData = defaultTownDataModule

game.Players.PlayerAdded:Connect(function()
    userTownData.PlotManager:RenderPlots()
end)

But when I try to call the :RenderPlots() method, i get an error from the ouput, saying that the method wasn’t found. I think that, when I call require(defaultTownData), the metatable get lost and it cannot find the :RenderPlots method.
Is there any way to make an object’s replica, keeping its metatable?

In the TownPlotManager module, you’re using .new() instead of :new(), which means that you’re making it a private function to that class. Because of this, in the defaultTownDataModule when you call TownPlotManager.new(), you’re not able to access the .new() function because it is private to the TownPlotManager script, essentially you cannot access that function from there.

Not sure what’s happening, because I can access the Town.TownPlotManager’s functions in the defaultTownDataModule. But when the table gets returned to TownDataLoader, it loses its metatable. Is it because of the require() function or something?​

You cant do require(a,b)
You have to require both separately

Oh, no, that’s just an example to reproduce the problem, it’s not real code. Sorry for the mistake.

Do you have the relavent code in its actuality rather than a representation of it?
Problems like this very rarely come out when vaguely described

That is not what colon syntax does. x:y(z, ...) is just shorthand for x.y(x, z, ...).

1 Like

You seem to return what Town.new returns, not the table it self, its very likely that Town.new just returns something else.

local Town = require(script.Town)
local TownPlotManager = require(script.TownPlotManager) --
return Town.new{
    TownPlotManager = TownPlotManager.new() -- args here
}

Perhaps you meant to do

local TownPlotManager = require(script.TownPlotManager) 

return {
    TownPlotManager = TownPlotManager.new() -- args here
}

If not, you need to show the Town.new function.

I get it now, I apologize for the misinformation, I’m not extremely familiar with Lua. Thanks for clarifying this.

1 Like

The Town.new function has the same template as TownPlotManager.new, an basic OOP object.

function Town:new(town)
    self = town
    setmetatable(self, Town)

    return self
end

So, the Town.new{TownPlotManager = TownPlotManager.new()} returns an town object with a TownPlotManager.new inside. The problem is, in the defaultTownDataModule, I can access the its returned object with functions, but in TownDataLoader I can’t.

I think that when I require() the module, the returned data loses its metatable. Not sure what’s happening.