Reputation: 552
I'm tying to understand that if in Kotlin there is a way to do this:
interface EnumClassX {
...
}
enum class EnumClassA: EnumClassX {
...
}
enum class EnumClassB: EnumClassX {
...
}
enum class EnumClassC: EnumClassX {
...
}
object Foo {
fun bar(enumClassA: EnumClassA) {
...
}
fun bar(enumClassB: EnumClassB) {
...
}
fun bar(enumClassC: EnumClassC) {
...
}
}
class Middle {
fun callFooBar(enumClass: EnumClassX) {
// What I have to do:
when(enumClass){
is EnumClassA -> {
Foo.bar(enumClass) // Note I don't even have to say "enumClass as EnumClassA" b/c it is already inside an "is" block.
}
is EnumClassB -> {
Foo.bar(enumClass)
}
is EnumClassC -> {
Foo.bar(enumClass)
}
}
// What I want to do:
Foo.bar(enumClass) // IDE says "None of the following functions can be called without the arguments supplied." Compiler can't figure out which flavor of enumClass has been passed in to call the appropriate bar.
}
}
Easily fixed with other simple inspection and switches as in the top example but was hoping there was a way to make it direct traffic accordingly? By that I mean that Middle.callFooBar is always called with one of the three types that have individual bar methods and just wondering if there is a way in Kotlin to make it call the right one without manually inspecting the type of enumClass.
Thanks! Scott
Upvotes: 0
Views: 66
Reputation: 17711
It's not possible, because you're using a static dispatch.
Statement
// callFooBar may be called with type CustomObjectA, CustomObjectB, or CustomObjectC
Is actually incorrect. The way compiler sees it, your method may be invoked with instance of any class, not only those three classes.
To use dynamic dispatch, you'll need to resort to old good inheritance. I know, inheritance is not cool nowadays, but your case is exactly what it's for:
interface EnumClassX {
fun bar()
}
class EnumClassA : EnumClassX {
override fun bar() { }
}
class EnumClassB : EnumClassX {
override fun bar() { }
}
class EnumClassC : EnumClassX {
override fun bar() { }
}
Theoretically, your code also should have worked with sealed classes (not enums, those are different):
sealed class EnumClassX {
abstract fun bar()
}
class EnumClassA : EnumClassX() {
override fun bar() { }
}
class EnumClassB : EnumClassX() {
override fun bar() { }
}
class EnumClassC : EnumClassX() {
override fun bar() { }
}
But it doesn't. My guess is that's simply because Kotlin team didn't want to complicate compiler further, but maybe I'm just missing some use case. Feel free to ask about why's that on discuss.kotlinlang.org
Upvotes: 1