Estoy tratando de entender que si en Kotlin hay una manera de hacer esto:

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.
    }
}

Se solucionó fácilmente con otras inspecciones e interruptores simples como en el ejemplo superior, pero ¿esperaba que hubiera una manera de dirigir el tráfico en consecuencia? Con eso quiero decir que Middle.callFooBar siempre se llama con uno de los tres tipos que tienen métodos de barra individuales y me pregunto si hay una forma en Kotlin de hacer que llame al correcto sin inspeccionar manualmente el tipo de enumClass.

¡Gracias! Scott

0
user888867 5 oct. 2019 a las 07:38

1 respuesta

La mejor respuesta

No es posible porque estás usando un envío estático.
Declaración

// callFooBar se puede llamar con el tipo CustomObjectA, CustomObjectB o CustomObjectC

Es realmente incorrecto. De la forma en que el compilador lo ve, su método puede invocarse con una instancia de cualquier clase, no solo con esas tres clases.

Para utilizar el envío dinámico, deberá recurrir a la buena herencia antigua. Lo sé, la herencia no está bien hoy en día, pero tu caso es exactamente para lo que sirve:

interface EnumClassX {
    fun bar()
}

class EnumClassA : EnumClassX {
    override fun bar() { }
}

class EnumClassB : EnumClassX {
    override fun bar() { }
}

class EnumClassC : EnumClassX {
    override fun bar() { }
}

Teóricamente, su código también debería haber funcionado con clases selladas (no enumeraciones, son diferentes):

sealed class EnumClassX {
    abstract fun bar()
}

class EnumClassA : EnumClassX() {
    override fun bar() { }
}

class EnumClassB : EnumClassX() {
    override fun bar() { }
}

class EnumClassC : EnumClassX() {
    override fun bar() { }
}

Pero no es así. Supongo que es simplemente porque el equipo de Kotlin no quería complicar más el compilador, pero tal vez me esté perdiendo algún caso de uso. No dude en preguntar por qué en discus.kotlinlang.org

1
Alexey Soshin 6 oct. 2019 a las 13:57