Kotlin supports a great deal of extension functions, allowing us to customize classes from other libraries a lot. The only feature we cannot extend is constructors.
Constructors are commonly imitated in libraries like JetBrains Compose:
class MyFunnyClass(val string: String)
fun MyFunnyClass(int: Int?) : MyFunnyClass = MyFunnyClass(int.toString())
However, there are a few problems with this syntax:
- IDE highlighting - the IDE considers this a function, not a constructor. As such, custom theming (like bold constructors) doesn’t work, and the IDE complains the function starts with an uppercase letter.
- Repetitive - this declaration repeats the name of the extended class three times when using
explicitApi
. - Java Interopability - Java will call this function
MyFunnyClass(42)
, notnew MyFunnyClass(42)
ormyFunnyClassOf(42)
.
I’m suggesting to introduce Extension Constructors, their syntax as such:
class MyFunnyClass(val string: String)
MyFunnyClass.constructor(int: Int?) : this(int.toString())
// or alternatively
constructor MyFunnyClass(int: Int?) : this(int.toString())
// and if you need more than one line...
MyFunnyClass.constructor(int: Int?) {
println(int ?: 42)
return this(int.toString())
}
Extension constructors always return the same type they extend.
Extension constructors won’t be able to use super(...)
, but only this(...)
, and won’t be appliable to enum
s and object
s.
Extensions constructors can also be useful when creating default implementations for interfaces.
And for my third point - interopability with Java - I suggest adding a default @JvmName
annotation:
@JvmName("myFunnyClassOf") // default, implicit unless overriden
MyFunnyClass.constructor(int: Int?) : this(int.toString())
As for interaction with the proposed context
syntax:
context(Int?) // extension inner class?
MyFunnyClass.constructor() : this@MyFunnyClass(this@Int?.toString())
fun main() {
val num: Int? = 42
with(num) {
MyFunnyClass()
}
num.MyFunnyClass()
}
Additionally, inline extension constructors will be especially useful.