Skip to content

RFC: Class Constructor Modifier - #240

Open
soyuta wants to merge 1 commit into
luau-lang:masterfrom
soyuta:class-constructor-modifier
Open

RFC: Class Constructor Modifier#240
soyuta wants to merge 1 commit into
luau-lang:masterfrom
soyuta:class-constructor-modifier

Conversation

@soyuta

@soyuta soyuta commented Aug 11, 2026

Copy link
Copy Markdown

Rendered

This RFC introduces a constructor modifier for declaring a class's constructor while allowing its name to follow existing Luau conventions.

class Car
	public IsDestroyed: boolean
	public Speed: number

	constructor function new(speed: number)
		self.IsDestroyed = false
		self.Speed = speed
	end
end

const car = Car.new()

Classes should not become difficult to understand or use, and I am concerned that the current direction may be making them unexpectedly more complex.
Even if this proposal is not accepted, I still hope classes will move in a direction that keeps them simple and intuitive.

@InfraredGodYT

InfraredGodYT commented Aug 11, 2026

Copy link
Copy Markdown

I've got a couple questions for this RFC:

  1. Why not just reserve constructor as a function like you do with super?
  2. Have you considered using static for factory methods instead of making constructor a modifier?

@soyuta

soyuta commented Aug 11, 2026

Copy link
Copy Markdown
Author

I've got a couple questions for this RFC:

  1. Why not just reserve constructor as a function like you do with super?
  2. Have you considered using static for factory methods instead of making constructor a modifier?
  1. Why not just reserve constructor as a function like you do with super:

If constructor is a reserved function name, then we lose the ability to use conventional constructor names like new or create.

There was already a lot of pushback against the __init -> .new approach in #210 because it wasn't considered intuitive.
If we avoid that, we'd basically have to construct classes only through function-call syntax like Class(), but there is already so much Luau code following conventions like .new and .create that I don't think we should simply throw those conventions away.

If we're going to use function-call syntax anyway, I think something more like the __init metamethod proposed in #210 would make more sense.

But if we want to preserve conventions like .new() and .create(), I think it's better to let the constructor name be written explicitly, as in constructor function new.

  1. Have you considered using static for factory methods instead of making constructor a modifier:

If constructors are implemented as static functions like they are now, inheritance becomes difficult to design around.

class Car
	public IsDestroyed: boolean
	public Speed: number

	function new(speed: number)
		return Car { IsDestroyed = false, Speed = speed }
	end
end

class ElectricCar extends Car
	public Capacity: number

	function new(capacity: number)
		const self = Car.new(math.max(50 - capacity * 2, 0))
		-- How do we know whether this Car is intended to become an ElectricCar, 
		-- or whether it should remain just a Car?
		-- We'd have no choice but to report an error here.
		self.Capacity = capacity 
		return self
	end
end

A normal static function has no way to express that Car.new(...) is constructing the base portion of an ElectricCar, rather than simply returning a Car.

That's why I think constructors need semantics beyond those of an ordinary static factory method.
Of course, there can still be static functions like fromFile, fromString, or Angles that build on the primary constructor.

@InfraredGodYT

InfraredGodYT commented Aug 12, 2026

Copy link
Copy Markdown

If constructor is a reserved function name, then we lose the ability to use conventional constructor names like new or create.

There was already a lot of pushback against the __init -> .new approach in #210 because it wasn't considered intuitive. If we avoid that, we'd basically have to construct classes only through function-call syntax like Class(), but there is already so much Luau code following conventions like .new and .create that I don't think we should simply throw those conventions away.

If we're going to use function-call syntax anyway, I think something more like the __init metamethod proposed in #210 would make more sense.

But if we want to preserve conventions like .new() and .create(), I think it's better to let the constructor name be written explicitly, as in constructor function new.

Standard conventions should be optional instead of enforced, and I believe that makes the function-call syntax superior to using/reserving a new or create method when instantiating a class.

If constructor is a reserved function name and you allow static factory methods like that utilize the primary constructor, then using conventional constructor names like new or create becomes a choice instead of being mandatory. While I like this RFC much more than #210, they both share the same problem of enforcing a specific pattern without a strong rationale. Common patterns shouldn't be treated like they're absolute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants