Classe [ARCHIVE]


creatorStore

github

wally


playground

Latest Update

:bookmark: What is Classe?

Classe is a smart class wrapper for Luau. It automatically calculates Object Structures, including Fields and Methods, using advanced Type Functions. Furthermore, Classe optimizes metadata lookups, ensuring high performance even with deep inheritance hierarchies

Basic Class

local Weapon = Classe.meta({ })

type Self = Classe.Self<typeof(Weapon)>

function Weapon.shot(self: Self)
	self.bullets -= 1
	print("Boom!")
end

function Weapon.construct(self)
	self.bullets = 10
	return self
end

return Classe.build(Weapon)

Inheritance

local Rifle, super = Classe.meta({}, Weapon)

type Self = Classe.Self<typeof(Rifle)>

function Rifle.aim(self: Self)
	self.isAiming = true
	print("aiming...")
end

function Rifle.construct(self)
	self.isAiming = false
	super(self)
        
	return self
end

return Classe.build(Rifle)

Standard Basic Class

--!strict

local Rifle, __class = {}, setmetatable({}, {
  Weapon.__meta
})

function __class.aim(self: Rifle)
  self.isAiming = true
  print("aiming...")
end

local __meta = {__index = __class}

export type Rifle = setmetatable<{
  isAiming: boolean,
  bullets: number,

}, typeof(__meta)> & Weapon.Weapon

function Rifle.new(): Rifle
  local self = Weapon.new()
  self.isAiming = false

  return setmetatable(self, __meta) :: Rifle
end

Rifle.__meta = __meta
return table.freeze(Rifle)

:stopwatch: Speed and memory

Classe is primarily focused on performance rather than memory efficiency.

During inheritance, the parent’s metadata is copied into the child. This should not significantly impact memory usage, since mostly function references and primitive values are copied, which are inexpensive on their own.

This approach improves method call performance because it avoids __index chains and additional lookups across the inheritance hierarchy.

If a class has subclasses and its metadata needs to be modified, __newindex is triggered. It iterates through all child classes and updates the corresponding data, while checking whether the metadata has been overridden in the subclass.


Here is a method call at the 99th level of inheritance (500k tests)

13 Likes

Next Update:

  • The ability to change the metadata of an already built class
  • make types more secure
1 Like

looks very solid. this module Is very useful in UI components maybe

1 Like

Release Update v1.0.0

  • The ability to change the metadata of an already built class
  • New type ISelf<M> for the self parameter of the init construct method
  • Minor changes in typing
1 Like

Probably going to use this, but can you add a benchmark, people are probably going to ask for it and it’ll make the resource more attractive

2 Likes

it looks like __index is faster than my method. With 100,000 tests per 100 inheritances, the __index was 30% faster or 1% slower. I don’t quite understand how luau optimizes all this. If this is not the case and I do not understand something, then tell me

1 Like

this might help

4 Likes

Release Update v1.1.0 (goodbye phtd)

  • Now you no longer need to manually work with PhantomData - Classe handles everything automatically. All data is now stored within the meta’s metadata while preserving scalability

private and public fields will not be implemented due to current limitations of Beta Luau Type Solver

1 Like

Release Update v1.2.0

  • Added a new lifecycle method - construct.
    construct is responsible for creating and initializing the object’s internal state (formerly handled by init)
    The init method is now executed after instance creation, in inheritance order (from the oldest ancestor to the most derived class)

  • Improved overall performance

  • Fixed immutability guarantees

4 Likes

Release Update v1.2.1

  • slightly improved performance and bug fixed
1 Like

Sorry, but I couldn’t use Classe due to the beta type solver freezing my studio while loading my big project and blowing up many memory.. Is it still usable without it?

1 Like

Yes, but without the Beta Luau Type Solver, type functions won’t work and will be marked as unknown syntax. All types will become errors

2 Likes

Ok so it might work with enabling script non-strict but the next day got me loaded in the project.. also how do you add parameters/options to the new function?
edit: it was by the construct function. gonna use this!! thanks!!!

1 Like

Weird enough it seems like one of the module type like Val doesn’t seem to work with autocomplete, but sometimes it worked when i was writing the attribute?

just the type if you were curious: export type Val<T> = typeof(setmetatable({} :: ValInternal<T>, {} :: typeof(Val)))

1 Like

You need to use the key function init

function MyClass.init(self: Self)
     -- this will be called automatically after the class is built
     -- you can do:
     self.state:Something()
     self:Something()
end
1 Like

Release Update v1.2.2

  • fixed incorrect overriding logic
1 Like

Im not sure how your Classe works, but init seems to be for when the class is built.. Im doing construct just because I need multiple objects to be created. In that case it doesn’t help me because it does the same problem, but finishing the key call manually gives me parameters preview

i apologize if im asking too much XD but also, most of my classes doesn’t show the parameters..

code:

--!strict
local Parent = script.Parent.Parent.Parent
local Classe = require(Parent.Misc.Classe)
local Val = require(Parent.Misc.Val)
local Types = require(Parent.Types)

local ObjectiveData = Classe.meta({}::Types.IObjectiveDataInstance,{})

export type Self = Classe.Self<typeof(ObjectiveData)>
type ISelf = Classe.ISelf<typeof(ObjectiveData)>

function ObjectiveData.construct(self:Self,ref:Types.IObjectiveData)
	
	self.ref = ref

	self._map = {}

end

function ObjectiveData.set(self:Self,key:string,value:any)
	
	self._map[key] = self._map[key] or Val.new(value)
	self._map[key]:set(value)
	
end

function ObjectiveData.getVal(self:Self,key:string) : Val.Val<any>

	--assert(self._map[key],`{key} not found within the data map!!`)
	
	return self._map[key]

end

function ObjectiveData.get(self:Self,key:string) : any
	local val = self:getVal(key)
	if not val then return end
	return val:get()

end

function ObjectiveData.serialize(self:Self) : {[string]:any}
	
	local data = {}
	
	for k,v in self._map do
		
		data[k] = self:get(k)
		
	end
	
	return data
	
end

return Classe.build(ObjectiveData)
1 Like

Как всегда фигня. Переделывай, брат.

1 Like

i would like an elaboration instead of just responding without any guidance🤨

1 Like

Release Update v1.2.3

  • bug fixs
1 Like