Class++ | Classes and OOP made easy and powerful with Access Specifiers, function overloading and more!

classppiconextended


github_v2 creatorStore WallyIcon

Latest Update:


:open_book: What is Class++?

Class++ is a module that aims to bring a class structure very similar to in languages such as C++ and Java. It brings access modifiers, function and operator overloading, inheritation, and many other concepts to Luau. It also supports type checking with a Type API!

:question: Why Class++?

It makes it so much easier to create classes, rather than focusing on figuring out how to use metatables just to be able to create a class system, you can just focus on what to add and overload in your class.

:star: Usage Examples

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ClassPP = require(ReplicatedStorage["Class++"])
local class = ClassPP.class

local Person = class "Person" {
    Public = {
        Name = "",
        Age = 0
    }
}

local newPerson = Person.new()
print(newPerson.Age) -- Prints 0!
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ClassPP = require(ReplicatedStorage["Class++"])
local class = ClassPP.class

local Car = class "Car" {
    Public = {
        Brand = "Lamborghini",
    },
    Private = {
        License_Plate = "XXXX"
    }
}

local newCar = Car.new()
newCar.License_Plate = "YYYY" -- This will error!

Classic Way:

local Car = {}
Car.__index = Car

function Car.new()
    local newcar = {}
    setmetatable(newcar, Car)

    newcar.Brand = "Lamborghini"
    newcar.License_Plate = "XXXX"

    return newcar
end

return Car

-------------------

local newCar = Car.new()
print(newCar.Brand)

This is just the start, to learn more about the features and the syntax, you can visit the documentation!.

:bookmark_tabs: API

Read the API
function classpp.class(className: string): (classData: classData) -> class

Creates a new class with the given classData table.

Parameters:

  • className: string
    The class name for the new class.
  • classData: table
    The classData table that contains the data about the new class.

Returns:

  • class

function classpp.getClass(className: string): class

Returns the class with the given className, if it exists.

Parameters:

  • className: string
    The name of the desired class.

Returns:

  • class

To see all the methods and properties in the API, you can visit the API Reference
page.

51 Likes

Not a bad implementation, but i will say it again and again. MiddleClass on github is the standard, and so far I’ve just not found anything better.

I took a look at your source, not bad but some of the code is not greatly comprehensible. Which is ok, you may be doing some really fancy things I am not so privy too. That being said, please comment the code, in many cases, someone might like your initial implementation but may need to tune it to cater to their needs and especially since Typed Luau is more advanced than most, it makes it considerably harder to understand what is going on.

That all being said, I will give it a look eventually down the line more practically.

One thing I have really noticed with many coders on this platform that are on the more skilled side that moved over to using VS coding and not coding directly with roblox, which is fine, tend to forget all the things that VS does automagically that roblox does not, and there are some people who don’t use that method of working to reduce issues. Just be aware of how you package and give out code and how you want to present it, the easier you make it the more people will want to use it. The more you make it readable and so even someone below your skill could come in and make edits or reasonable adjustments to fit their needs the better and more widespread it could be used.

If you are making things for others, think about the end user working with it.

Again, it looks pretty solid from my general review but just some tips on how you could get more widespread use on it.

3 Likes

Thank you! I was really looking forward to opinions like these.

Now to answer your concerns, if you’ve noticed in the init.luau file on the repo, I already tried adding some comments and even added the upcoming local documentation feature as a small test on top of the class method. So yes, more comments and explanations are coming soon in the source code.

Besides that, for the sole reason of explaining things better and making things easier for other developers, I’ve created a documentation page, so developers won’t have to figure out everything on their own, and I’ve pretty much documented everything in there.

Also, right now I’m working on making a model to upload to Creator Store, so developers can easily get the model without going through GitHub.
(Although it would be better for them in that case since updates and important changes are going to be documented there.)

Yup I hear you! And I will be open with you that I am biased when it comes to typed lua. I am not exactly sold on it just yet, but I will come around slowly I am sure.

And it’s good, def give middle-class a look though, its got literally every feature you could ask for out of a class implementation.

That being said I will keep my eye out and you can message me when i can review it better with comments there.

I’ve gave it a look, and it looks pretty nice, although my mission is to create an advanced class architecture with most of the features that are present in other languages.

For example, C++ was my main inspiration, the syntax is not hard to understand, it has many features such as function overloading, operator overloading, access specifiers, inheritation, and more. I even took some features from Java, like the final and abstract non-access specifiers. I took all of these features and decided to implement them in Luau, with the syntax very close to C++ so it’s easily understandable and easier to work with.

Originally, Class++ wasn’t written in full Typed Luau, but I decided to give it a shot, along with the native mode, and it significantly improved the performance. Especially with native, the interpreter gets used less, and the compiler does the job.

And good news, in the future I heard there will be a new type solver, which will improve the performance and the Typed Luau experience even further.

1 Like

It will be interesting to see how it goes, atm typed and untyped don’t really do anything different from what I have read, but please point to the documentation if they have changed that recently!!

Typed lua is transpiled into base lua as of what I remember reading but perhaps that’s changed and that would be huge if they were doing that long term. Yea, native is really nice bit of a heavy memory cost but in highly computation heavy areas its Def worth the cost for sure!

For real, if they are skipping the transpiled aspect I would be really interested to know.

1 Like


And here’s an image of a benchmarking test I’ve ran.
(Note: "Class++ Native & Strict is an older version of Class++, the performance is even better now with further optimizations)

You got me so excited! :sob:, I thought “Theres no way he figured out how to make the custom classes have types!”

image

I don’t know if such a feature would even be possible. typeof(setmetatable({}, T))?
But congrats! this resource is really interesting!

1 Like

Do you mean automatic typechecking for the class members? Trust me, I really tried. I don’t think it’s possible. Especially in this system where the classData properties are being transferred through several functions.

Though you have one solution: Since objects belong to the base type userdata, you can easily cast a custom type to them, and they will work perfectly fine!

Also, thank you!

1 Like

Updated the links to include creator store!

Is this for object oriented programming?

Yes, this module aims to make OOP much easier for new and old developers!
I’m open to feedback by the way, make sure to send feature requests and bug reports if you have any!

Release 1.1.0


  • Improved performance while creating new objects, it should be quite faster to create them now.
  • Other performance improvements.
  • Added more comments and explanations on how certain functions work, and added support for an upcoming Studio documentation feature.

A performance comparison picture between 1.0.0 and 1.1.0:

Also I added a new creator store link to make getting the module easier, make sure to check it out!

2 Likes

Updated the documentation with some new features and fixes, and updated the main post with a comparision.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ClassPP = require(ReplicatedStorage["Class++"])
local class = ClassPP.class

local Car = class "Car" {
    Public = {
        Brand = "Lamborghini",
    },
    Private = {
        License_Plate = "XXXX"
    },
    changeLicensePlate = function(self, plate:string)
        self.License_Plate = plate
        return self
    end,
}

local newCar = Car.new()
newCar:changeLicensePlatw(“YYYY”)

can i do it like this?

Oh no, that would give an invalid access specifier error. Members must always be placed inside access specifiers. Try putting the function inside an access specifier, for example, Public like below:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ClassPP = require(ReplicatedStorage["Class++"])
local class = ClassPP.class

local Car = class "Car" {
    Public = {
        Brand = "Lamborghini",
        changeLicensePlate = function(self, plate: string) -- We put this function inside the Public Access Specifier, so it can be accessible from everywhere.
           self.License_Plate = plate
        end,
    },
    Private = {
        License_Plate = "XXXX"
    },
}

local newCar = Car.new()
newCar:changeLicensePlate("YYYY")

Check out the documentation for more information access specifiers! You should read the entire thing through, it would be very useful.

Release Beta 1.2.0


  • Improved performance on accessing an object’s Private and Protected access specifiers.
  • Updated the final and abstract functions to now accept multiple classes with a new syntax.
  • Util.inClassScope function now accepts a new optional defaultLevel value that determines the default call stack level the function will start doing the checks on.

A performance comparison picture between 1.1.0 and 1.2.0:

1 Like

Release Beta 1.3.0


  • Improved performance when creating and accessing an object.
  • Updated the API Reference and Tutorial documentation to include a new feature: static members.

Introducing a new function:

class.static(accessSpecifier: string, name: string, property: any)
  • Classes can now have static members using this function, just like in Java and C++, they belong to the class, and will not replicate to the objects created from the class.
  • They’re global, and will be the same everywhere.
  • You can access the static members through the class object like:
    class.<memberName>.property or class.<memberName>.p for short.

Check out the documentation for more info!

Release Beta 1.3.1


  • Fixed cyclic tables causing stack overflow when the object is getting destroyed.
  • Fixed when a member is set to false, that member is no longer indexable.
  • Performance improvements.

Make sure to get the latest version to get the most amount of performance, and fixes!

I have put a tool into the .new() function and constructor function, its says This class has no member named “Tool”.