How to do OOP with modules?

Disclaimer: Pretty new to Lua, learning as I go. Quite experienced with other programming languages and OOP in general though.

Problem: I’m trying to encapsulate my player data in a table that I can save and load from a DataStore. Naturally, each player needs their own instance of this data since player 1’s progress in the game is not going to be the same as player 2’s progress. I’ve heard that most people do this with modules, so I tried to make a simple module to handle this:

local PlayerInstanceData = {}
	
Result.UserId = UserId
Result.Level = 1
Result.Experience = 0
Result.Essence = 0
Result.Items = {}


function PlayerInstanceData:GrantEssence(Amount)
	self.Essence = self.Essence + Amount
end

return PlayerInstanceData

Now, this doesn’t work because when I require this module it always returns the exact same instance, like a singleton. So I thought I would be clever and do this instead.

local PlayerInstanceData = {}

function PlayerInstanceData.new(UserId)
	local Result = {}
	
	Result.UserId = UserId
	Result.Level = 1
	Result.Experience = 0
	Result.Essence = 0
	Result.Items = {}
	
	return Result
end

function PlayerInstanceData:GrantEssence(Amount)
	self.Essence = self.Essence + Amount
end

return PlayerInstanceData

But now this has the problem that the value returned from new() doesn’t have the GrantEssence function on it.

What is the accepted paradigm for doing this kind of thing?

Your second example is pretty close to what people do.
On your 2nd line you’d have:

PlayerInstanceData.__index = PlayerInstanceData

And then instead of doing return Result, you’d do:

return setmetatable(Result, PlayerInstanceData)

This sets the metatable of Result to your “class”, and since its __index points to itself, whenever you access a field from your instance that’s not defined in it, it’ll default to grabbing from PlayerInstanceData.

6 Likes

You’re right, I was close! I suspected it had something to do with metatables, but I haven’t really learned about them yet, so I wasn’t quite sure what. But your explanation makes sense, thanks!

If you’d like a good resource oriented towards OOP in Roblox, there’s a very good tutorial thread currently up that brushes up on OOP, provides examples and also has inheritance if that interests you. It’s a recommended resource for developers new to the paradigm or even for seasoned developers who are looking to brush up some dusty knowledge.