Help with Object Oriented Programming

I’m extremely new to OOP (Object Oriented Programming) and metatables so please excuse me if my script looks bad. I just started learning today.

Anyway.

Goal: I’m trying to make a function that gives player Cash using OOP.

Problem: The code won’t work when I test it. It gives the following error in the in the output:

Script:

local StatFunctions = {}

StatFunctions.__index = StatFunctions

function StatFunctions.new(player)
	local self = {}
	setmetatable(self, StatFunctions)
	
	self.Player = player
	self.Cash = player.leaderstats.Cash.Value
	self.Captures = player.leaderstats.Captures.Value
	self.Kills = player.leaderstats.Kills.Value
	self.Deaths = player.leaderstats.Deaths.Value
	
	
	
	
	return self
end

function StatFunctions:AddCash(player, amount)
	
	self.Cash += tonumber(amount)
end


return StatFunctions

I’m testing the function by giving the player Cash when they join.

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local StatFunctions = require(ServerStorage.StatFunctions)

Players.PlayerAdded:Connect(function(player)
    StatFunctions:AddCash(player, 10)
end)

What I’ve tried: So many things that it makes my brain hurt.

Can someone help me with this?

2 Likes

You need to create a new StatFunctions object, then call AddCash to it:

local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local StatFunctions = require(ServerStorage.StatFunctions)

Players.PlayerAdded:Connect(function(player)
    local PlayerStats = StatFunctions.new(player) -- Create a new object
    PlayerStats:AddCash(player, 10) -- Call the method from here
end)

Ohhhhhhh. Thanks for helping me out.

But now I get a new error:

I just tried :WaitForChild, which doesn’t work either.

How are the leaderstats added to the player

Like this: (not the entire script. Just the leaderstats part which works fine)

local function OnPlayerAdded(player)
	-- Setup leaderboard stats
	local leaderstats = Instance.new('Folder')
	leaderstats.Parent = player
	leaderstats.Name = 'leaderstats'

	local Captures = Instance.new('IntValue')
	Captures.Parent = leaderstats
	Captures.Name = 'Captures'
	Captures.Value = 0

	local Cash = Instance.new('NumberValue')
	Cash.Parent = leaderstats
	Cash.Name = 'Cash'
	Cash.Value = 0
	
	local Kills = Instance.new('IntValue')
	Kills.Parent = leaderstats
	Kills.Name = "Kills"
	Kills.Value = 0
	
	local Deaths = Instance.new('IntValue')
	Deaths.Parent = leaderstats
	Deaths.Name = "Deaths"
	Deaths.Value = 0
end

Players.PlayerAdded:Connect(OnPlayerAdded)

I’m not sure why indexing and WaitForChild don’t seem to work, is there any both scripts can be combined, or do they have to be separate?

Also, for WaitForChild, does it throw the Infinite Yield Possible warning, or does it not seem to do anything?

When I try :WaitForChild, nothing appears in the output, but the code still doesn’t work.

They have to be separate since the leaderstats script is in a Server Script.

Ok, I think I understand what’s happening, If you’re expecting the value of StatFunction.Cash to appear in the leaderboard after changing it, it won’t happen because of the way variables work.

You would have to try something like this:

local StatFunctions = {}

StatFunctions.__index = StatFunctions

function StatFunctions.new(player)
	local self = {}
	setmetatable(self, StatFunctions)

    local leaderstats = player:WaitForChild("leaderstats")
	
	self.Player = player
	self.Cash = leaderstats.Cash -- Save a reference to the objects
	self.Captures = leaderstats.Captures
	self.Kills = leaderstats.Kills
	self.Deaths = leaderstats.Deaths
	
	
	
	
	return self
end

function StatFunctions:AddCash(player, amount)
	self.Cash.Value += tonumber(amount) -- Add to the 'Value' property of the object
end


return StatFunctions

Now you should see changes appear on the leaderboard

1 Like

It still doesn’t work unfortunately. No errors in the output, either.

You should use a OOP module if you can’t do this type of OOP.

I use Classic when it comes to OOP:

The thing about being a Programmer is that I like to make things on my own. I wouldn’t learn anything by using a Module.

Did you load the OnPlayerAdded function?

Look at the bottom of the leaderstats script. I already put it there. I would’ve gotten an error if I hadn’t

I think its because self is not called.

Use this:

local StatFunctions = {}

StatFunctions.__index = StatFunctions
StatFunctions.self = nil

function StatFunctions.new(player)
	local self = {}
	setmetatable(self, StatFunctions)

    local leaderstats = player:WaitForChild("leaderstats")
	
	self.Player = player
	self.Cash = leaderstats.Cash -- Save a reference to the objects
	self.Captures = leaderstats.Captures
	self.Kills = leaderstats.Kills
	self.Deaths = leaderstats.Deaths
	
	
	
	
	StatFunctions.self = self
end

function StatFunctions:AddCash(player, amount)
	StatFunctions.self.Cash.Value += tonumber(amount) -- Add to the 'Value' property of the object
end


return StatFunctions

If you look at my code properly, self is in fact a table:

I am saying that you are not making self to the whole module. Only to the new function.

This is definitely not the way to implement object oriented programming. Each call to the constructor will override the StatFunctions.self attribute and you don’t even get an object from the constructor.

1 Like

That’s exactly what I thought. Do you know what I’m doing wrong?

1 Like

I think some more investigation needs doing into why this doesn’t seem to be working - Help with Object Oriented Programming - #9 by HugeCoolboy2007

1 Like

When I construct an OOP Class, I would return the one set with the metatable like so:

local StatFunctions = {}

StatFunctions.__index = StatFunctions

function StatFunctions.new(player)
	local self = {}
	
	self.Player = player
	self.Cash = player.leaderstats.Cash.Value
	self.Captures = player.leaderstats.Captures.Value
	self.Kills = player.leaderstats.Kills.Value
	self.Deaths = player.leaderstats.Deaths.Value
	
	
	
	
	return setmetatable(self, StatFunctions)
end

function StatFunctions:AddCash(player, amount)
	
	self.Cash += tonumber(amount)
end


return StatFunctions