Concepts: Object Oriented Programming in Roblox

UPDATE: I have made massive changes to this thread, highlighting issues brought to my attention by @EtiTheSpirit and other people who gave feedback. I have unfortunately hit the character limit of 32k, so I will have to create separate threads for descriptions of all the metamethods as well as practical use cases. Thank you for reading this!

7 Likes

Very helpful!

But as an OOP newbee, I still don’t understand how to use it in real roblox game.

There is a gap between what OOP is and how to apply it in real case.

3 Likes

There are many cases where OOP is useful . I once made a Gun System and I used OOP for its Setting and Other stuffs . Its based on how you think you can implement OOP to something.

1 Like

I was looking for a tutorial for object-oriented programming.
It’s an awesome tutorial.
May I translate this post and post it on the korean site?
if you ok, I’ll highlight the original link and post it!

2 Likes

I remember reading an article similar to this before, but this seems more in-depth. Nice job.

1 Like

I don’t see an issue with that, glad you like the tutorial :smiley:

Thanks for allowing :slight_smile:
Good luck!

Very helpful :slightly_smiling_face:

1 Like

As a tip, if you do not want to have an if statement in every single method you create under your “class” as show here:

You can set up your code like this:
(code shown below is for example purposes)

--ModuleScript
local Object = {}
Object.ClassName = "Object"
Object.__index = Object

function Object:Method()
    return self.Name
end

return {
    new = function(name)
        local newObject = setmetatable({}, Object)
        newObject.Name = name or Object.ClassName
        return newObject
    end
}
--Script/LocalScript
local Object = require(path_to_module)

local newObject1 = Object.new("Jon")
local newObject2 = Object.new()

print(newObject1:Method()) --> "Jon"
print(newObject2:Method()) --> "Object"

print(Object:Method()) --> Method would not be a valid member of the table returned

This also prevents “newObjects” from being able to call the “new” method or the constructor.

EDIT: Replaced the old section with this new, better way of setting up the code.

7 Likes

This is a really good tutorial, thank you so much! Here is an example I made following along in this tutorial:

Example

ModuleScript (in ReplicatedStorage)

local Character = {}
Character.__index = Character

function Character:SayHello()
	print("Hello, my name is " .. self.name .. "!")
end

function Character:ShareHobby()
	print("My hobby is " .. self.hobby .. ".")
end

function Character:Age(int)
	self.age += int
	
	print(self.name .. " aged " .. int .. " year(s), and is now " .. self.age .. " year(s) old.")
end

return {
	new = function(name, age, hobby)
		local object = setmetatable({}, Character)
		
		object.name = name or "Character"
		object.age = age or 0
		object.hobby = hobby or "Programming"
		
		return object
	end
}

ServerScript (in ServerScriptService)

local Character = require(game.ReplicatedStorage.Character)

local char1 = Character.new()
local char2 = Character.new("John Doe", 34, "Gaming")

char1:SayHello() --> Hello, my name is Character!
char2:SayHello() --> Hello, my name is John Doe!

char1:ShareHobby() --> My hobby is Programming.
char2:ShareHobby() --> My hobby is Gaming.

char1:Age(1) --> Character aged 1 year(s), and is now 1 year(s) old.
char2:Age(2) --> John Doe aged 2 year(s), and is now 36 year(s) old.
5 Likes

Amazing. Just amazing.

I’ve been trying to learn OOP for a while, then I came to the devforum and found this through a search. You’re the best explainer I’ve ever seen.

When you’re explaining an issue-solving concept, your approach is genius. Instead of straight-up explaining what the concept is, you start with problematic code (for demonstration purposes), and then explain the problem, and then explain how the concept solves this problem.

This kind of explaining makes it stick into your head, by providing an actual example, and showing you what the code would be with and without the concept.

I believe you deserve top contributor for this, it’s honestly a brilliant contribution.

4 Likes

Semicolons and commas both have the function of separating arguments/parameters in tables.
(See here for their different uses)
I even tested this myself, using either one you can use Car:Drive() and Car.Drive()

I believe you are confused. I have stated you can use either semicolons or commas. What you are quoting is unrelated.

Thanks for this tutorial man. I made a pet follow system using OOP and being able to determine owner of a pet by doing self.Owner which I find quite useful! I am going to use OOP for now on :D.

2 Likes

Static class methods don’t have a this pointer that refers to the object because it’s a class level method. Though, you are right about methods existing only for the class to reduce memory, your terminology and use case of static is incorrect.

In Lua, the __index metamethod allows us to define methods on the class itself instead of each object, but it would not be considered static because the methods are invoked through the object itself. Apart from that, I do agree, it’s a very important practice to reduce the overall memory of each object.

Yeah I meant this is passed in for member methods, not static methods.

Oh yeah I did get confused sorry about that, I must of gotten mixed beweenbetween semi colons and colons or something like that.

2 Likes

I know this was from a while ago, but I’m sure people scrolling by will have the same question. Well, to answer this, let’s say you want to make Semi-Auto guns and Auto guns. Here’s how you could apply OOP:

You would have a base class called Object.

Object can have a property called Name.

You could have Gun as a subclass of Object, and then you could have SemiGun and AutoGun as subclasses of Gun.

Gun would have a method called Reload(), and a property called Ammo.

AutoGun would have a method called StartFiring(), and another one called StopFiring().

SemiGun would have a method called Fire().

In this case, you would be taking advantage of Inheritance, mostly. In situations like this where two classes (SemiGun and AutoGun) are going to need the same function (Reload()), you can use inheritance and avoid copy-pasting code, following D.R.Y to a greater extent.

4 Likes

Really good tutorial. This helped me learn that metatables aren’t hard at all compared to normal table. Only thing I’m unsure about is creating new properties within instances since their metatables are locked. I’m going to read up about that though. Really good tutorial, I really love it and the information it provides. Thank you OP!

3 Likes

The way you put it in simple terms helps to understand, thank you a lot for this document!

1 Like