Help with OOP Class Constructors

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!

I want to create a class constructor that acts similarly to “Instance.new()”, but for my own classes. Here are the things I want to include:
-When I call “Weapon.new()”, it returns an object based on the class name specified in the first parameter.
-The object returned will inherit all of the properties from the Weapon class.
-The object returned will be type checked, so it can give script suggestions.

  1. What is the issue? Include screenshots / videos if possible!

I have been trying to figure out how to implement my idea, but all of my ideas came up short.

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I have used ChatGPT and many posts on the forum, but I haven’t found anything that can perfectly resolve this.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

local SS = game:GetService("ServerStorage")
local Weapons = script.Parent:WaitForChild("Weapons")

local Weapon = {}
Weapon.__index = Weapon

function Weapon.new(className : string, owner : Player)
	local class = Weapons:FindFirstChild(className)
	if not class then return {} end
	class = require(class)
	local new : class.Types = class.new(owner)
	
	new.Damage = 50 -- these properties are inherited from this class
	new.FireRate = 0.5
	
	return new
end

function Weapon:Init()
	--Default Code if specified weapon class doesn't have an init method
end

function Weapon:Powerup() -- this method is inherited from this class
	self.FireRate /= 3
	self.Damage *= 3
	
	self.Owner.Character.Humanoid.WalkSpeed += 50 -- this property comes from the specified class
end

return Weapon

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

2 Likes

Hey there, in order to fix this, it’s pretty simple. Instead of having a whole other constructor for creating classes, you can simply just do local new = {} and then right before your return just do setmetatable(new, Weapon). This should cause your weapon class to behave the way you’re intending it to.

If I’m misunderstanding your question, just let me know

1 Like

Thanks for the suggestion! The new code works much better now.
However, I also wanted type checking to be used in the objects. For example, when I put a colon after the object variable, I want to be suggested all of the methods available in the object.

2 Likes

You will need to make your own type for that.

export type WeaponClass = {
    ["Ammo"]: number, --ammunition
    ["Shoot"]: (Weapon) -> (nil) --procedure takes weapon as parameter and returns nothing
}

Then, you could access it from outside the module.

--in module
local NewWeapon: WeaponClass = Weapon.new()
--outside of module
local NewWeapon: Weapon.WeaponClass = Weapon.new()
3 Likes

Here’s a tip: You can just do
function Weapon.new(className : string, owner : Player): WeaponClass
to make it automatic.

1 Like

good point, thanks for pointing that out.

1 Like

I like this solution, but I’m also wondering about how I can not only have the types from the Weapon Class, but the types from the Base Class. Basically, the object created through “Weapon.new()” will have properties and methods suggested to me from both classes. Is this possible, and how can I do it?

1 Like

By “Base Class”, do you mean the methods the weapon will inherit? As in things already in the module? You can just include them in the type.

1 Like

You can do this by setting the metatable of your weapon subclasses to the base weapon class:

local WeaponSubclass = {}
WeaponClass.__index = WeaponClass

local Weapon = require(Path.To.Weapon)

setmetatable(WeaponSubclass, Weapon) -- setting the metatable of your weapon subclass to 'Weapon' (aka inhertiting from it)

function WeaponSubclass.new()
	local new = setmetatable(Weapon.new(), WeaponClass)
	-- ...
	return new
end


return WeaponSubclass 

Essentialy what we have done in the constructor is creating a new instance of weapon and setting its metatable to our WeaponSubclass but since our WeaponSubclass inherits from Weapon everything should work.

local myWeapon = WeaponSubclass.new()
myWeapon:Init()

In this example when we try to access the Init function. What would happen is: We will try to find the key in the myWeapon table, It was not found so we continue to its metatable: WeaponSubclass we also cannot find the key there so we go to WeaponSubclass’s metatable: Weapon, we search there and find the Init function that we can now call!
I hope this helps (:

To learn more about OOP and inheritance here is an amazing tutorial:

To learn more about OOP with type checking here is another amazing tutorial:

2 Likes

Sorry that I made it confusing!
Base is actually a test weapon that will be created from the main Weapon class constructor. Sorry for the confusion!

1 Like

You just need to cause the subclass to inherit from the main class, just as @LobsterGames99 described.

1 Like

I also want to be able to call the “Weapon.new()” function to create the object from the subclass. How can I do this?