I was trying to create the following class:
class MyClass {
var foos: List<Foo> = listOf()
constructor(foos: List<Foo>) {
this.foos = foos
}
constructor(bars: List<Bar>) : super() {
this.foos = bars.map { bar ->
Foo(bar)
}
}
}
However, I get an error saying:
Platform declaration clash: The following declarations have the same JVM signature ( (Ljava/util/List;)V):
I understand that they are both List objects, but they are typed with generics so I was sure it would not be a problem.
There can be multiple constructors in a class. However, the parameter list of the constructors should not be same. This is known as constructor overloading.
A Kotlin class can have a primary constructor and one or more additional secondary constructors.
The technique of having two (or more) constructors in a class is known as constructor overloading. A class can have multiple constructors that differ in the number and/or type of their parameters. It's not, however, possible to have two constructors with the exact same parameters.
You encounter this problem because in java there exists something called type erasure. And because kotlin uses the JVM it is also affected by this limitation. To give a TL;DR;
The generic type is retained in the .class
file so java knows that the class (in your case List
) is generic. But it can't keep track of the generic type of an instance. So instances List<Foo>
and List<Bar>
are both handled in their raw type form at runtime (List
). Keep in mind that generics are only used at compile time to ensure type safety.
To overcome this limitation, you can make use of operator overloading in kotlin. The operator we're looking at is ()
which let's you invoke any instance. By using a companion object
we can even make this
invoke
look like a constructor, and be invoked like one (MyClass()
). Your code can look like this:
class MyClass(var foos: List<Foo>) {
companion object {
operator fun invoke(bars: List<Bar>) = MyClass(bars.map(::Foo))
}
}
Which allows you to call it simply like this:
val mc1 = MyClass(foos) // calls constructor
val mc2 = MyClass(bars) // calls companion.invoke
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With