Make require(module) initiate a new instance

I have two models, ModelA and ModelB
Each of them have a script that requires a module script and just calls the “init” function i defined.

This is the init function

function module:init(model)
	self.name = model.Name
	print(self.name)
	wait(1)
	print("waiting")
	wait(1)
	print(self.name)
end

The output is:

ModelA
ModelB
▶ waiting (x2)
▶ ModelB (x2) 

Any idea how I can make each script have its own instance going on?
I’d like my output to not be 2 ModelB’s at the end, but instead ModelA and ModelB

I’ve already obviously tried using model instead of self

I would like to point out that ChatGPT recommended cloning my module scripts. Sounds like it should definitely work, but it also sounds quite hacky. Any tips?

Because modules cache and return the same object every time upon require (and they only run on the first require), you would probably need to pass the script to the module:init function and then store the reference to the script as an indexer and then a value as the model. You would have to index it through the module’s reference storage every time

local module = {}
module.objectRefs = {}

function module:init(callingScript, model)
    if not module.objectRefs[callingScript] then
        module.objectRefs[callingScript] = model
    end
    
    print(module.objectRefs[callingScript]) -- should give the same model every time
end

It may also be helpful to look into Lua’s version of object oriented programming using a metatable as it allows you to call methods passing the relevant object (in your case the object unique to the script) and allows for inheriting methods and such. It would also allow more than one object per script.

1 Like

Yeah, to be honest, my init function receives the parent of the script. Do you think that would be enough? Or would I need to actually pass the script itself.
But damn, I didnt know modules cache and return the same object every time upon require. I thought it was like a Class in other languages, and I could make new instances of it.

But okay, i see what you mean
Youre trying to say i should make new tables under the objectRefs table. And make it so that the index of each table is the different script.
I kind of hoped I could just save props to the self or the instance of the module and then be able to use it anywhere. Just because I got like 10/15 functions there that require that property. But okay, if youre saying that there isnt a good way to make each module:init use its own instance, then i guess I’ll just pass the property to each function.

It depends, is the script’s parent unique, or would each of the scripts inside of that parent share the same model? If either of those are ok, then yes it would be ok to pass the script’s parent instead of the script itself.

Modules do cache but Lua does have its own implementation of prototype-based classes using metatables.

Typically they’re laid out as so:

local module = {}
module.__index = module -- allows tables in the constructor (later) to inherit anything inside of the module table

function module:doSomething() -- self is omitted here but is still defined
    -- really it's syntactic sugar for 'function module.doSomething(self)'
    -- self would be the 'object' (a table with a metatable), not the module
    print(self.prop)
end

function module.new() -- constructor
    local self = setmetatable({}, module) -- this is the "object" which can be indexed for its methods. since it's missing the 'doSomething' field, the __index metamethod will be "fired" which points to module so self would inherit module.
    
    self.prop = true
    
    return self
end

return module

Later in a script,

local class = require(path.to.module)

local obj1 = class.new()
obj1.prop = false

local obj2 = class.new()

obj1:doSomething() --> false
obj2:doSomething() --> true

It would be relevant in your case if you were to make “objects” which contain the module (like a sort of wrapper I guess), which would allow you to apply properties, children etc to the object or the model based on the object’s ‘model’ field instead of applying it to the module

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.