All about Object Oriented Programming

I like the tutorial, however personally I prefer Java’s approach to OOP.

I wonder if someone would make a thing comparing it to other languages?

Hey there!
While Java has a class-based object oriented programming style, where classes can extend and implement others, LUA (unfortunately) does not. Using metatables in LUA is unfortunately as close as we can get to Java’s class-based style, since LUA does not have a built-in class framework.

Hope this helps!

3 Likes

Thank you so much! I do have one question, can something like a static variable or instance variables be made?

Yep! You can create static variables by just setting defining the variable. You can do this by (in the case of using a ModuleScript) writing code on the lines of this.

local Class = {}
Class.__index = Class

Class.staticVariable = "Hey there! This is a static variable" -- A static variable that can be accessed from anywhere, and doesn't change when you make an instantiated class unless you manually change it with "Class.staticVariable = ..."

function Class.new()
    local self = setmetatable({}, Class)
    
    self.classVariable = "Hey there! This is a class variable" -- A variable that only the instantiated version can access.

    return self
end

Hope this helps! :smiley:

4 Likes

Is it possible to make a default constructor? For example in Java you would have

public class Car {

String carModel;
//Default Constructor
public Car(){
 carModel = "";
}
//Constructor
public Car(model){
 carModel = model;
}


}

Is it also possible to make objects send to multiple scripts or in a value?

Lua doesn’t have any function overloading, so there is usually only 1 constructor.

2 Likes

You can write one function to use different combinations of variables though.

How would I go about putting multiples of different objects from the same module scripts in tables? From what I have tried it overwrites the previous object.

ModuleScript:

local slot = {}

slot.__index = slot

function slot.new(index)
	local newSlot = {}
	setmetatable(newSlot,slot)
	slot.Index = index
	
	return newSlot
end

function slot:getName()
	return self.Index
end

return slot

Main:

local mod = require(game.ServerScriptService.Slot)
local obj1 = mod.new("Name")
local obj2 = mod.new("Name2")
local array = {obj1,obj2}
print(array[1]:getName())

The output says “Name2” instead of “Name1”

You are storing the new(index) into the slot module, not the slot object that gets created.

do
newSlot.Index = index

1 Like

How would I have classes inherit metamethods such as __tostring or __add?

Since the metamethod invocation uses rawget, it doesnt seem to look up the chain of classes to find the base implementation.

i dont know too much about OOP and I am trying to learn. My question is: how would a car table became a real car on roblox? I would have to call Car.new() and latter create the car with the info on table? That does not make sense. Can I make the Car.new() return an actual car object?

In the constructor (Car.new) you would create the car model and then usually you’d have a property like car.Model or car.Instance that you assign the Model to.
Now when you want to interact with the model you just access the property.
In other cases where you don’t need the extra functionality you can return the model directly instead.
This comes with the disadvantage that now you can’t use methods like car:Accelerate()*

  • Technically you can if you “wrap” the model but that’s a different concept
2 Likes

This would be a easier way,

local Car = {}
Car.__index = Car

function Car.new(position, driver, model)
	local self = setmetatable({
		Position = position,
		Driver = driver,
		Model = model,
	}, Car)
	
	return self
end

return Car
4 Likes

It may be easier for you, but your code looks a bit more messy than the OP’s code.

4 Likes

Messier? It looks more readable than just doing plain old newcar.VAR = var,

1 Like

For you it does, for others it there is a chance it’s not.

1 Like

Personally I prefer this version:

function Car.new(position, driver, model)

	local self = setmetatable({}, Car)
	
	self.Position = position
	self.Driver = driver
	self.Model = model

	return self
end

This is the least ambiguous version IMO albeit admittedly it does look redudant compared to yours.

2 Likes

Alternate way of formatting

----------------------------------------------------
-- Define Class Attributes
----------------------------------------------------
Car = {
	Position = nil;
	Driver = nil;
	Model = nil;
	Speed = nil
}

----------------------------------------------------
-- Define Class Methods
----------------------------------------------------
function Car:Boost()
	self.Speed = self.Speed + 5
end

----------------------------------------------------
-- Define Class Constructor
----------------------------------------------------
function Car.new(tbl)
	local newcar = tbl or {}
	setmetatable(newcar, Car)
	Car.__index = Car
	return newcar
end
2 Likes

If I have this:

local PlayerModule = {}
PlayerModule.__index = PlayerModule

-- Constructer function to create a new character  
function PlayerModule.new(character)
	local newCharacter = {}
	setmetatable(newCharacter, PlayerModule)
	
	newCharacter.Name = character.Name 
	newCharacter.Stamina = 100 
	newCharacter.BonusHealth = 0 
	table.insert(characters, newCharacter)

	return newCharacter	
end

return PlayerModule 

How would I get the newCharacter that I created without doing .new() every time. I thought of making a table and inserting the newCharacter into that table to get it that way. Am I missing something about OOP here?

So my solution is now this:

local PlayerModule = {}
PlayerModule.__index = PlayerModule

local characters = {}

-- Constructer function to create a new character  
function PlayerModule.new(character)
	local newCharacter = {}
	setmetatable(newCharacter, PlayerModule)
	
	newCharacter.Name = character.Name 
	newCharacter.Stamina = 100 
	newCharacter.BonusHealth = 0 
	table.insert(characters, newCharacter)

	return newCharacter	
end

-- get the character 
function PlayerModule:GetCharacter(name)
	for i, v in pairs(characters) do 
		if v.Name == name then 
			return v 
		end
	end
end

return PlayerModule 

I’m not sure if this is the correct way to do it.