Planning to create a keep for <Extension Construct...
# language-proposals
l
Planning to create a keep for Extension Constructors.
Copy code
class Foo(bar: String)
// three mentions of Foo in explicit api! Java interop is horrible! The IDE doesn't know this is a constructor, complains about the naming, and stylizes incorrectly!
fun Foo(bar: Int?): Foo = Foo(bar.toString())

// An extension secondary constructor! Java thinks it's a static method named "fooOf".
Foo.constructor(bar: Int?) : this(bar.toString())

// Alternate syntax
constructor Foo(bar: Int?) : this(bar.toString())

// And extension "inner" classes, for free!
context(String)
Foo.constructor() : this(this@String)
1
a
What difference would this have compared to creating a function with the same name as the class ?
3
l
IMO "constructor" shouldn't be a concept outside the class... also constructor is pretty limited in respect to functionality. You can't
inline
(which means you can't have
reified
or low-cost lambda), you must call
this()
first (which means you can't have elegant parameter validation).
1
s
what would happen if someone defined an
operator fun invoke(bar: Int?)
on Foo.companion? which would get called when I do Foo(5) ?
d
Presumably
invoke
would be called, which is the same thing that already happens when someone adds a method to a base class with the same signature as your extension method.
b
I'm a fan of the
invoke
approach because it gets treated the same as constructors in the IDE (which isn't that strong of a reason I suppose) and doesn't fill the intellisense with overloads like functions to. Plus it's linked more explicitly at the language level so e.g. refactorings are guaranteed to work without having to special case check that same-named functions are also updated. In the future it should also be possible to use
invoke
for classes without companion objects with static extensions
l
@Ayfri Java will be able to see the function as
fooOf()
instead of
Foo()
(which looks weird, as Java uses the
new
operator) without declaring an explicit
@JvmName
, and more importantly - you won't need to repeat the name of the extended class three times when using explicit API.
@stantronic exactly the same as in any other case where there are multiple functions available and the compiler cannot determine which should be used.
The
invoke
approach is nice, yet:
Copy code
operator fun Foo.Companion.invoke(): Foo = Foo()
//           1                       2     3

void main() {
    FooKt.invoke(FooKt.Foo.Companion); // invoke functions
    FooKt.fooOf(); // extension constructors
}

// plus, the IDE still doesn't recognize a constructor use and cannot style it like "normal" constructors.
As for `inline`ing, I believe there's no reason not to allow an inlined extension constructor - it could be a great use-case. As for having to call
this()
, I assume one could just allow extension constructors not to "extend" a constructor if they call it.