Send Metatable from one module script to another

I have two module scripts (Client - Side) and I want to send the metatable of Module1 to Module2 with all the functions.

Further explanation:

Module 1

local Module = {} Module.__index = Module
local Module2 = Path_To_Module

Module.New = function(self)
local table = {Money = 79, Gold = 3}
for _,i in pairs(self) do table[_] = i end

return setmetatable(table, Module)
end

function Module:AddOre()
return “Test”
end

function Module:Send()
Module2.New(self):Print()
end

return Module

Module 2

local Module = {} Module.__index = Module

Module.New = function(self)
self.Diamonds = 69
return setmetatables(self, Module)
end

function Module:Print()
print(self.Diamonds, self.Gold, self:AddOre())
end

return Module

So I want to call module1 like: Module.New({Coal = 12, Iron = 0})

So now inside module1 Metatable it should have Coal, Iron, Money, Gold and with I call Module1:Send() , it should add this Metatable to Module2 Including the function in module1 AddOre

Just in the spirit of avoiding an xy problem, why do you want to do this, exactly?

Also, BTW, you can just edit your previous post instead of creating a new one. It would help to avoid spam if you closed one or the other.

3 Likes

in trying to achieve this because of having each module with the same meta table, they can share just share One.

Also I know you can edit, but I wanted to provide a better insight of what I’m trying to achieve.

Just return the metatable and thats it.

1 Like

I get that, but why do you need to do this? What’s the use case? I’m just trying to figure out how to answer your question.

Because metatables are just tables. You can send them in a function parameter like normal:


local function PrintMetatable(t)
    local m = getmetatable(t)
    if m then
        for k, v in pairs(m) do
            print(k, v)
        end
    end
end

local t = {1, 2, 3}

PrintMetatable(t) --> nothing

local m = {__index = "test"}
setmetatable(t, m)

PrintMetatable(t) --> __index   test

But I don’t think that’s really what you’re asking, so I’m asking at a high level what you’re trying to do.

2 Likes

Correct, a metatable is “just a table” and I can just return it, but it doesn’t retrieve the functions.

I guess I didn’t explain my situation and issues throughly.

I want to set the metatable from Module1 to Module2, so in Module2 I’m able to call functions, variables, etc from the Module1.

Not to sound like a broken record, but why? This is a really weird thing to want to do, and I suspect there’s a better solution. You’re using the idea of modules and OOP in a very non-standard way, and it probably bite you later on.

Once more: why are you trying to do this? Is this a mining game? What do these modules represent?

I’m sorry for being so pedantic, I’m really trying to help you answer this, but the question is very hard to answer without more context.

At the very least, give example code with how you would even call these modules and what the expected output would be.

1 Like

I’ve explained my goals several times throughout this topic, and I mean it doesn’t provide any importance knowing what in trying to use this for, isn’t the devforum for advice or solutions to your problems?, not interrogations

They’re just trying to help, because without explaining why you’re doing this, it looks like you’re using metatables in a weird way that can be avoided. If you responded to their questions without getting defensive, they could’ve found a much much simpler solution.

If anything you could’ve just said you’re not comfortable sharing why and that would’ve saved you about 3 replies.

2 Likes

Sorry, but it’s not that I’m comfortable sharing, it’s just that I told them what I wanted to achieve, but that keep stating that it’s a weird way of doing it

They understand what I’m trying to do, but keep stating that it’s weird tho

But the solution they’ve provides doesn’t return “functions” only variables, I know because I’ve tried it before.

But I still appreciate the reply’s, though it doesn’t solve my problem :+1:

I’m not sure if I quite understand you, but if you wanted Module2 to inherit all of Module’s functions, you can loop through every element inside of Module, and insert it into Module2 if it is a function.

I’ve re-named Module to Module2 to discern the obvious differences between modules.

Module2.New = function(self)
	for k,v in pairs (Module) do
		if typeof(v) == "function" then 
			Module2[k] = v
		end
	end

Yeah, that what I’m trying to do, but unfortunately this doesn’t work either, I’ve tried it.

the functions in module1 are called with ”:” so adding each function to the meta in module2 won’t work. (Or at least that’s my discussion, for its failure) thank you for coming to my Ted talk

Ha! Yes, it is for that :slight_smile:

I gotta interrogate you because you keep saying “what”, not “why”.

Anyways, I’ll give it a shot.

The properties (Diamonds, Money, Gold) are in the table objects, not the metatables.

The functions (AddOre, Send, Print) are in the metatables Module1 and Module2.

So if you want Module2 to inherit functions from Module1, you can set the metatable for Module2 to be an instance of Module1 itself. Something like this:

-- Module1
local BaseClass = {}
BaseClass.__index = BaseClass

function BaseClass.new(prop)
	local self = {
		Property = prop or "default"
	}
	setmetatable(self, BaseClass)
	return self
end

function BaseClass:Print()
	print("BaseClass:Print", self.Property)
end

function BaseClass:PrintMore()
	print("BaseClass:PrintMore", self.Property)
end

-- Module2, inherits from Module1
local ChildClass = {}

function ChildClass.new(parent)
	local self = {}
	return setmetatable(self, {
		__index = function(t, k)
			-- lookup in ChildClass first, or else the parent instance
			return ChildClass[k] or parent[k]
		end}
	)
end

function ChildClass:PrintMore()
	print("ChildClass:PrintMore", self.Property)
end

-- no extra metatable for ChildClass because we make a new one in the constructor

-- tests

-- create an BaseClass
local baseInstance = BaseClass.new()
baseInstance:Print()      --> BaseClass:Print default
baseInstance:PrintMore()  --> BaseClass:PrintMore default

-- create a ChildClass from that instance
local childInstance = ChildClass.new(baseInstance)
childInstance:Print()     --> BaseClass:Print default
childInstance:PrintMore() --> ChildClass:PrintMore default

-- modify base instance, affects child
baseInstance.Property = "modified"
baseInstance:Print()      --> BaseClass:Print modified
baseInstance:PrintMore()  --> BaseClass:PrintMore modified
childInstance:Print()     --> BaseClass:Print modified
childInstance:PrintMore() --> ChildClass:PrintMore modified

-- modify child instance, doesn't affect base
childInstance.Property = "modified again"
baseInstance:Print()      --> BaseClass:Print modified	          (UNCHANGED)
baseInstance:PrintMore()  --> BaseClass:PrintMore modified        (UNCHANGED)
childInstance:Print()     --> BaseClass:Print modified again      (CHANGED)
childInstance:PrintMore() --> ChildClass:PrintMore modified again (CHANGED)

Maybe that’s close to what you’re looking for.

2 Likes

This is likely because your code has errors, I was able to successfully test it.

: is syntantical sugar for this: Module.Function(Module).

In your 2nd module, you were using setmetatables instead of setmetatable.

local Module2

local Module = {} 
Module.__index = Module

Module.New = function(self)
	local table = {Money = 79, Gold = 3}

	return setmetatable(table, Module)
end

function Module:AddOre()
	return "Test"
end

function Module:Send()
	Module2.New(self):Print()
end

Module2 = {} 
Module2.__index = Module

Module2.New = function(self)
	for k,v in pairs (Module) do
		if typeof(v) == "function" then 
			Module2[k] = v
		end
	end

	self.Diamonds = 69
	return setmetatable(self, Module)
end

function Module2:Print()
	print(self.Diamonds, self.Gold, self:AddOre())
end

Module.New({Coal = 12, Iron = 0})
Module2.New({})

print(Module2:AddOre())

image

Additionally, in the example above, the __index metamethod still points to Module1 instead of Module2 (the memory addresses correspond with each other):

image

I hope this helps.

Again as previously stated, there are better ways on inheriting modules, this code base simply caters to your usecase.

1 Like

My code didn’t contain any prominent errors, if my reply was stated as “setmetatables” instead of “setmetatable” then it’s probably just a typo, taking in to consideration that I wrote the reply and code on my phone, and wasn’t pasted from an physical script in my game.

But I’ll still give it a try, update on the current status of the code later :+1:

I’ll give this a try as well, update on the current status of the code later :+1:

Also just to let everyone know, non of your solutions worked.