Can you create actual classes and how?

They are an interpreted way to do it, pretty much, yeah.

There are several equivalent ways of emulating OOP in lua. Metatables are the correct way, this is the alternative:

Functions are equivalent to objects as you can return other functions from them (the technical term is a “closure”, read the Wikipedia article if you want to know more.) These are in some ways stronger than metatables because they allow you to have private properties and methods, but tend to be slower because Lua is optimized for metatables. Take the following constructor as an example

function Thing(prop1, prop2)
    local self
    local function PrivateMethod1(a)
        print(self.publicprop3)
        prop1 = prop1 + a
        return prop1
    end
    self = {
        publicprop3 = 0,
        PublicMethod1 = function(b)
            self.publicprop3 = self.publicprop3 + 1
            return prop2 + PrivateMethod1(b)
        end
    }
    return self
end

For usage:

local thing = Thing(2,3)
thing.publicprop3 = 5
thing.PublicMethod1(5)

If you need to extend a “class” I suggest you wrap and delegate instead (this applies to metatable based oop as well). Extension is unnecessary in a duck typed language like lua.

2 Likes

Although it does effectively the same thing it’s three time longer than using metatables or python ‘Classes’
It’s not quite equivalent but more an attempt of copying classes properties.

Lua is not an OOP language and doesn’t have classes or inheritance. The Roblox platform is what makes the environment OOP. The workflow can be achieved in any language given you implement it yourself and with metatables you can get pretty close syntax wise as well. For further reading: PIL-16

That depends on what is being done. CollectionService is not necessarily an appropriate alternative for classes, depending on what it is you’re trying to accomplish.

(I went with a Wikipedia link that I thought was relevant because it seems to be a common location to go to. Feel free to look up resources or reading material on classes on the Internet that aren’t Wikipedia - perhaps directly on sites for coding languages instead.)

1 Like

No. Metatables themselves aren’t classes; they’re useful when it comes to object-oriented programming because of the __index metamethod, which allows for inheritance. Using a prototype-based approach (wherein classes don’t exist; everything is an object, and prototype objects act as the blueprint/template for other objects), the system usually falls along the lines of:

Code-wise, this would look something like:

-- Object
local Object = {}
function Object:new()
    local o = {}
    local mt = {__index = self}
    setmetatable(o, mt)
    return o
end

-- Object > Animal
local Animal = Object:new()
Animal.X = 0
function Animal:Walk(distance)
    self.X = self.X + distance
end

-- Object > Animal > Dog
local Dog = Animal:new()
function Dog:Bark()
    print("You hear a 'woof' from " .. self.X .. " studs away.")
end

-- example:
local dog1 = Dog:new()
local dog2 = Dog:new()

dog1:Walk(10)
dog1:Bark() --> You hear a 'woof' from 10 studs away.

dog2:Bark() --> You hear a 'woof' from 0 studs away.

Although this approach does not provide real privacy, it is commonly seen as the simplest and most lightweight method; I personally prefer it.

5 Likes

Yes, that’s true metatable aren’t class although they are similar.

They are not; they just provide extra functionality to data. There’s really no such thing as a ‘metatable’ either - they’re just a table that has been assigned the metatable of some datum through setmetatable.

Metatable are pretty similar to classes I do think they are often use for the same thing in the same way it isn’t just sugar code.

How are metatables similar to classes?

As I just stated they are used in a very similar way to do the same thing.

I don’t see how they are. Classes act as a template/blueprint for the creation of objects. Metatables provide data with additional behaviour. Please explain your thoughts.

Metatables are more like Objects I do agree although I still think they can have Methods and Data and you can use them as a template to create multiple of them.

Metatables are neither objects or classes. It wouldn’t make sense for metatables to store methods or data in the same way that an object would; they exist only to provide metadata about data and change its behaviour. I don’t see how metatables can be used as a template, either.

A thing that store methods and data is basically an object or oop related

50 char

Metatables aren’t designed to hold methods or general data. Let’s take this to PMs.

If you want to have a kind of class-based workflow, you can have a Lua equivalent of a constructor, using the .new special method. This method is (by convention) used as a constructor. You may know it from calls such as

local frame = CFrame.new(0,0,0)

Here’s an example of how these are generally programmed:

function MyClass.new(init)
  local self = setmetatable({}, MyClass)
  self.value = init
  return self
end

The return self line is the line which gives this constructor-like behaviour, as it returns an instance of that table and its methods. So, essentially, it returns an instance of the module. So, you can then use that object to access methods and fields as though you’re referencing an object.

self is a constructor method or setmetatable is ?..
or are both ?

Neither are a constructor on their own. The self keyword is simply a short way of a module referring to itself. For example:

local myClass = {}

local countOfCats = 0

function setCats(self, number)
    self.coundOfCats = number

The self property just allows the module to refer to itself. In returning it, you give the invoking script access to that too. This is why, for example, you can see the X value of a CFrame from the script which created it, but only after you created it with CFrame.new

self is not a keyword, though it is highlighted at such. It takes advantage of the colon sugar syntax.

Remember that this code:

function name:key(a, b)

end

Is sugar syntax for this code:

function name.key(self, a, b)

end

And that this code:

name:key(1, 2)

Is sugar syntax for this code:

name.key(name, 1, 2)

You can pass anything in.

name.key(something, 1, 2) -- something will be the self implicit argument

self is an implicit parameter.

6 Likes