To begin, let us talk about what OOP is; Object-Oriented Programming is a form of programming in which objects are used instead of loose-leaf code. This programming form has many benefits, including making development easier to maintain and update, simulating real-world use, slightly higher memory but increased organization, reusability, and sustainability.
If you understand these concepts by heart, you will be able to find a job in the software development industry. Keep in mind OOP programming is not understood by some people thus knowledge on such a topic is exponentially useful long term.
There are four fundamental principles to follow in OOP, Encapsulation, Abstraction, Inheritance, and Polymorphism. These all play an essential role in making OOP a practical and useful form of development; hence why many big tech corporations use OOP in their development.
Before continuing, please note in OOP, functions are referred to as methods. Methods represent the transfer of messages/data or procedures associated with a class. Methods essentially are what a function does in an object/class. Also, note what a superclass is. A superclass is a class that will inherit from a class. For example, I have a CarSuperClass; this superclass contains all of the functions needed for every car in my game. Instead of assigning all of the variables and methods needed in each car class, I can inherit from the CarSuperClass.
Now let us take a more in-depth look to see what these four principles are.
Encapsulation is the idea that we can hide direct access to data by using a private key while using available methods. This principle is more used in C#, C++, Java, and Python; however, it is usable in Lua. An example in Roblox would be that I had a PlaneClass; only the pilot would have access to fly the plane in this class. Therefore, we give the pilot a key directly from the server to the pilot’s client so only the intended user can access data. The pilot can only call the fly function with his private key, leading to only Encapsulation.
Abstraction is the idea that we only want the user or client to see its functionality rather than its framework. This principle allows users to see what the code does instead of how the code works. For example, I have a PlayerData superclass; I have methods that deal directly with saving and loading player data in this class. When the player joins, the player object/instance will inherit from the new data object I have created. Furthermore, instead of having a script that indirectly deals with player data, the class now directly deals with player data.
Inheritance is one of OOP programming’s essential principles; this principle is the idea of the relationship between 2 or more classes. If I were to create a class that deals with player combat and then created a character class, I would inherit the player combat class inside the character class. By doing this, I no longer need to define the combat methods in the character class as I am inheriting all that the combat class methods. This inheritance shortens and organizes code and makes code easier to maintain and update in the long term.
Polymorphism is the idea an object can act or behave in many ways. The most common use we see in modern development is in Java; this occurs when a class references a variable that refers to a child class. An example of this would be to create a player data superclass that contained a method called SaveData. Then if I were to inherit this class in a character class, we would have an inheritance. Now the character class has the SaveData method. If I were to change this SaveData function to add health instead of saving data, polymorphism would be.
Now that we have the four fundamental principles in OOP, we need to learn how to achieve OOP in Lua. In Lua, to achieve OOP-like functionality, we use a unique table called a metatable. These tables give us the ability to create methods and classes that can follow the four principles.
Now, what is a metatable? Metatables are tables that allow us to change behavior. Metatables can define how Lua computes expression, as well as global functions. Even though each table in Lua has its metastable, we would still need to define and expand upon the table using setmetatable and using the given metamethods.
Lets start with the most simple form of metatables.
local Table = {} -- Here we can see a table that we just made. Now we need to add functionality to it.
--[[
To do this we need to use metamethods. There is a list of metamethods on the roblox WIKI; the metatable page lists all of their uses and how to use them.
]]
--Lets start with the first step. We will be using the .__index metamethod.
--[[This method allows us to check if the index is in the given table; if they are not, it will index itself. However, if there is no reference present, then it will return nil.]]
Table.__index = Table -- We refrence the table we want to pull the information from.
--[[
Now that we have setup the index function we can add methods to the table.
]]
--Lets start with our constructor.
function Table.New(Name, Shape, Size, Color)
-- here we create our init method. This creates the class once called.
return setmetatable({
Name = Name;
Shape = Shape;
Color = Color;
Size = Size;
}, Table)
end
local Object = Table.New("Apple", "Square", "55", "Green")
local Red_Object = Table.New("Red Apple")
print(Object.Size) -- 55, here we can print out this objects properties by indexing them.
print(Red_Object.Name) -- Red_Object, we can make as many objects as we want; they will all have different data.
Now we know what a class looks like. However, how can we use the four principles that we mentioned earlier? Good question, ill show you.
This is an example of Encapsulation:
local Plane_Class = {} -- we init our table
Plane_Class.__index = Plane_Class -- we make the index
--[[
Note the usage of : instead of . The key : is used when calling self or the object that the function is called from. The key . is used when init the class.
]]
function Plane_Class.New() -- we make our constructor to make the class
return setmetatable({
Key = "ABC_DE_ADF_A123";
},Plane_Class)
end
function Plane_Class:FlyPlane(PKey) -- make the fly method
if self.Key == PKey then
print("Take off vrrrr")
end
end
local Plane = Plane_Class.New() -- create the plane object
Plane.__metatable = "Locked" -- here we lock the MT so it cannot be changed
Plane:FlyPlane(Plane.Key) -- we attempt to fly the plane, this will print Take off
This is an example of Abstraction:
local PlayerDataClass = {}
PlayerDataClass.__index = PlayerDataClass
function PlayerDataClass.New(P)
return setmetatable({
Player = P;
}, PlayerDataClass)
end
function PlayerDataClass:SaveData()
print("Do stuff with data brrr")
end
function PlayerDataClass:LoadData()
print("Do more stuff with data")
end
--Player joining
local Player_1 = PlayerDataClass.New("Jimbo_123xx")
local Player_2 = PlayerDataClass.New("Legendary_Foxx2015")
Player_1:SaveData() -- Save Data
Player_2:LoadData() -- Load data
This is an example of Inheritance :
local PlayerCombat = {}-- setup our inherit table
local CharClass = setmetatable(PlayerCombat, {}) -- setup our 2nd object to inherit with
CharClass.__index = CharClass -- index the new object we created so we can get all the functions
function PlayerCombat.New(Player) -- create new player combat constructor
return setmetatable({
Player = Player;
}, PlayerCombat)
end
function PlayerCombat:Fight() -- we make a fight function that will be inherited
print("Pow Pow")
end
function CharClass.Spawn() -- spawn function
return setmetatable({
CharHealth = 100;
}, CharClass)
end
function CharClass:Heal() -- heal function
print("Heal stuff :D")
end
local CharClass = CharClass.Spawn() -- create a char class.
print(CharClass:Heal()) -- call the heal method
print(CharClass:Fight()) -- we call the inherited fight function
Polymorphism will not really have a needed use in Lua; It is good to know; however, I have never really had a reliable use. If you were to spend time learning C++ or Java, then this would be important. However, given the context of Lua and its limitations, there is no practical use.
Suppose you stayed till the end of this short tutorial on OOP, then congrats! You know everything you need to know for the first two years of a CS degree.