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! , I thought “Theres no way he figured out how to make the custom classes have types!”
I don’t know if such a feature would even be possible. typeof(setmetatable({}, T))
?
But congrats! this resource is really interesting!
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!
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!
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
’sPrivate
andProtected
access specifiers. - Updated the
final
andabstract
functions to now accept multiple classes with a new syntax. -
Util.inClassScope
function now accepts a new optionaldefaultLevel
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:
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
orclass.<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”.
Can you send the script here so I can take a look?
Forgot to include, I’ve updated the API Reference a little bit to show the properties in a better style.
This is the script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local ClassPP = require(ReplicatedStorage["Class++"])
local class = ClassPP.class
local toolClass = class "Tool" {
constructor = function(self, tool)
if tool and tool:IsA("Tool") then
self.Tool = tool
self.Configuration = require(self.Tool.Config)
self.Tool.Equipped:Connect(function()
self.equipped = true
end)
self.Tool.Unequipped:Connect(function()
self.equipped = false
end)
end
end,
Public = {
equipped = false,
Tool = nil,
Configuration = {},
}
}
CollectionService:GetInstanceAddedSignal("Tool"):Connect(function(tool)
if tool:IsA("Tool") then
local newTool = toolClass.new(tool)
end
end)
This is the Error : {Class++}: This class has no member named "Tool".
I see what you mean now, this is a common mistake that people encounter when creating classes using my module.
This is mostly related on how dictionaries work in Luau, when you set a key to nil
, you’re actually removing that key from the table. In this case, the key Tool
is being set to nil in the Public
access specifier, and since you’re setting the key Tool
to nil
, Lua automatically removes it from the table, which in the final classData
, the Tool
member does not exist.
To solve this issue, instead of setting it to nil
, you can set it to false
.
Here’s your updated code:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local ClassPP = require(ReplicatedStorage["Class++"])
local class = ClassPP.class
local toolClass = class "Tool" {
constructor = function(self, tool)
if tool and tool:IsA("Tool") then
self.Tool = tool
self.Configuration = require(tool.Config)
self.Tool.Equipped:Connect(function()
self.equipped = true
end)
self.Tool.Unequipped:Connect(function()
self.equipped = false
end)
end
end,
Public = {
equipped = false,
Tool = false,
Configuration = {},
}
}
Oh man i didnt know this about dictionaries, thank you.
Release Beta 1.4.0
- Performance improvements.
- Fixed some bugs.
- Updated the final method to support functions with the syntax below:
local class, final = ClassPP.class, ClassPP.final
local Test = class "Test" {
Public = {
test = final(function(self, ...)
print(self, ...)
end),
}
}
A performance comparison picture between 1.3.1 and 1.4.0: