Classes for luau module

I made a module that lets you make classes in luau

Here it is

class.rbxm (1.7 KB)

Example: (ChatGPT generated the examples for me because I am too lazy)

local new, class, extends = require(module)()

class "Person" {
	constructor = function()
		this.name = "Unknown"
		this.age = 0
		print("Person created: " .. this.name .. ", Age: " .. this.age)
	end,
	greet = function()
		print("Hello, my name is " .. this.name)
	end
}

local john = new(Person)()
john.name = "John"
john.age = 30
john:greet() -- Should print: "Hello, my name is John"

class "Employee" [extends "Person"] {
	constructor = function()
		super()
		this.jobTitle = "Unknown"
		print("Employee created: " .. this.name .. ", Job Title: " .. this.jobTitle)
	end,
	work = function()
		print("I am working as a " .. this.jobTitle)
	end
}

local jane = new(Employee)()
jane.name = "Jane"
jane.age = 28
jane.jobTitle = "Engineer"
jane:greet() -- Should print: "Hello, my name is Jane"
jane:work()  -- Should print: "I am working as a Engineer"

local original = {
	name = "Original",
	details = {
		age = 25,
		profession = "Developer"
	}
}

class "Vehicle" {
	constructor = function()
		this.brand = "Unknown"
		this.model = "Unknown"
		print("Vehicle created: " .. this.brand .. " " .. this.model)
	end,
	drive = function()
		print("Driving a " .. this.brand .. " " .. this.model)
	end
}

class "Car" [extends "Vehicle"] {
	constructor = function()
		super()
		this.numDoors = 4
		print("Car with " .. this.numDoors .. " doors created.")
	end,
	honk = function()
		print("Honk! Honk!")
	end
}

local myCar = new(Car)()
myCar.brand = "Toyota"
myCar.model = "Corolla"
myCar.numDoors = 4
myCar:drive() -- Should print: "Driving a Toyota Corolla"
myCar:honk()  -- Should print: "Honk! Honk!"

To use it you do

local new, class, extends = require(module)()

with new you can do

new(class)(…)

or

new “class”(…)


There is also ‘super’ and ‘this’ but it will show as “not defined” cause it is only defined in constructors

Feedback will be appreciated

7 Likes

Also while making this I ironically found somebody who made something similar

Check this out too

1 Like

The interface is lovely! It’s what Luau should have been like from the start. But, it isn’t built-in, so I have reason to believe the type-checking/autocomplete isn’t working well for this? I only feel comfortable coding with correct types!

1 Like

Pretty similar! Only main difference in presentation is how all of my methods would function with just dots and no colons, staying true to JS methods! I am pretty curious on how similar they are in the actual source and what you may of done differently

I’ve thought of typing my class system before, it’s very possible since it’s pretty much just a metatable wrapper with some distinctions, so I believe if the author created and exported a Class type that you could use a union type on with your table, it would work fine!

What’s the performance like? And is there a documentation for this?
And hasn’t this type of class system been created by other people already?
This person for example has created an extremely similar system to yours, but with seemingly better features and control over classes, what’s the advantage in yours?

Take a look at a class module on github called “MiddleClass” literally converting that or upgrading it to your liking would be the Boss mode. It is by far the best Class module I have ever worked with in Lua.

All my suggestions would be to make it behave more like middle class, but again I am biased because to date I have not found a better class module period.


Just something to bare in mind for anyone looking at this and considering “type” strictness in your coding. For lua, adding type strictness has three main bonuses.

  1. More implicit explanation of variable types so documentation can be sparcer if you are doing everything else right.

  2. It can help with error checking

  3. Fancy Auto complete

The biggest Con atm is it adds a lot of visible jargon that takes awhile to get used too and understand. Currently Typed lua is a transpiled language so there is zero benefit to speed or performance by being typed.

Fundamentally, if you are doing strong formatting of your code, naming your variables well, and having a system for tagging their types, your already doing it. Technically.

That being said, it may make moving from one language to another easier if you are already quite comfortable with it, but I highly suggest not getting too caught up in needing typed code. IMO I would consider it as something should do as your clean up pass on a system of code but not when you are writing a new system first pass.

There may be some tricks it can do that I would have to drill into more, but I am a bit noob at some of the really advanced trickery of typed, but from what I have read a lot of that this pretty obscure.

All that being said, I have not looked at the module directly yet, but are you tracking your objects types as they are created to mitigate conflicting Types, are you offering any sort of way of storing creating objects to be cleaned up.

How would this look if you created Person in one module, and then wanted to extend in another module. What does the syntax do then?

There is, engineers have made it clear in recent updates that Typed Luau improves compile time with native mode and allows for significant speed increase even in strict mode only.
A new type solver/system is also on the way with support for even function types.

It’s very similar to TypeScript, you should go take a look at it.

So I should add type annotations?

Could you link me that article ?

Also how do you think I could make it better than this MiddleClass module

Maybe, I would love to see the article where they say that, because everything I have read says they WANT it to do that in the future but currently it does not.

Can you give me examples of what you want to happen

Well you could convert it to luau, first, and see where it could benefit from the new things luau can do.

I suggest even if you don’t do that, you should give it a good long look because the guy who made it is pretty emaculate in his coding and he may do some things in some ways you didn’t think about.

I’ve been using the thing for years, and I just recently learned how to properly create an interface (“extend”) which is like a mixtable, for it. That allows for no inheritance or inheritance based on implementation.

I have fancied the idea of updating it to luau typed myself, but atm I still feel a way about typed.

I feel like it its finiky in how you can pass type references to other scripts. It can be unreliable at times for that. Aka, I can’t have a centraliy defined typing that automatically is caught by the intellesense when I require it elsewhere or when I instanciate the class. That being said, I could spend more time on seeing if I am just missing some new tricks they have added. But when I have played with it, it tends to be really finiky if I am not basically re-hard type referencing it every time.

Another thing it has built in checking of "am I a class, or am I a classof, you can look at some of that documentation there for a lot of good built ins for it.

It auto tracks all your construction of class names, so you don’t have a name collision automatically.

It also has a very straight forward implementation for if you want it to flow through a parent construction phase, or if you want the subclass to ignore it.

Again, I could go on and on, when I was figuring out stuff early on, a few years ago, I tried out a TON of different class modules that are out there, and its just the cleanest I have found.

That being said, if you can solve some of that type aspecting of it, that would be awesome. I would love if when I type defined a function for the function that the instatiations of it would automatically get the intellsense for it.

As I have said, outside of what I have read, the intellesense is like the biggest thing with it all.

Native stuff is very specific in it’s uses, and its for computation and raw math like things mostly.

I have not heard or seen anything about Strict typing improving performance to any significant degree.

“Luau compiler currently doesn’t use type information to do further optimizations, however early experiments suggest that we can extract further wins. Because we control the entire stack (unlike e.g. TypeScript where the type information is discarded completely before reaching the VM), we have more flexibility there and can make some tradeoffs during codegen even if the type system isn’t completely sound. For example, it might be reasonable to assume that in presence of known types, we can infer absence of side effects for arithmetic operations and builtins - if the runtime types mismatch due to intentional violation of the type safety through global injection, the code will still be safely sandboxed; this may unlock optimizations such as common subexpression elimination and allocation hoisting without a JIT. This is speculative pending further research”

From the current documentation

With the recent updates and the new upcoming type solver, this old documentation will also be updated soon.

1 Like

Cool, can’t wait to see !! It stands that eventually it should offer performance increases eventually since the whole point is to help with allocation and inference to help the compiling, but we shall see!!

That is exciting to hear, it will be interesting to see how much of a boost it gives to outweigh the overhead for the work with it.

I’ve been using strict typing for the past few months, and I’ve run some benchmarking using Boatbomber’s Benchmarker, and without me making any updates to it, it has gotten faster. (Not using any APIs)