为什么Kotlin密封类不能实现子类型函数重载?

时间:2018-05-14 18:37:30

标签: kotlin polymorphism overloading

假设我已将密封的类用于服务器响应:

sealed class Response{
    class Success: Response() 
    class ErrorA: Response() 
    class ErrorB: Response() 
}

虚假的回应:

fun getResponse(): Response{
    val r = Random()
    return when (r.nextInt(3)) {
        0 -> { Response.Success() }
        1 -> { Response.ErrorA() }
        2 -> { Response.ErrorB() }
        else -> { throw IllegalStateException() }
    }
}

我想处理回应。我目前可以使用这样的东西:

fun handle(response: Response) = when (response) {
    is Response.Success -> { handle(response) }
    is Response.ErrorA -> { handle(response) }
    is Response.ErrorB -> { handle(response) }
}

然后编译器将确保处理所有情况。一个很棒的功能!

但是,为什么我不能做这样的事情:

class ResponseHandler(){

    fun handle(success: Response.Success) {}

    fun handle(error: Response.ErrorB) {}

    fun handle(error: Response.ErrorA) {}
}

并致电

ResponseHandler().handle(response)

这实现了同样的目的,但是没有编译,我的问题是这样的:就像编译器在运行时确保所有情况都在when语句中处理一样,为什么同样的逻辑不能应用于方法重载?

任何进一步阅读的信息或推荐都会非常有帮助。感谢

2 个答案:

答案 0 :(得分:2)

原则上可以完成(主要是通过自动生成handle(response: Response) = when ...方法)。但我认为这不可能。 Kotlin中的重载与Java / Scala /其他JVM语言中的重载基本相同,并且为这么少的好处引入一个主要区别并不是一个好主意(当然这不适用于Kotlin的when -具体)。

如果您需要,可以在fun handle(response: Response)内定义相同的ResponseHandler(并制作其他handle方法open,这样它实际上很有用。)

答案 1 :(得分:1)

这个问题可以分解为这个简化的例子:

fun calc(i: Int) = i * 2
fun calc(d: Double) = d * 2

fun main(args: Array<String>) {
    val i: Number = 5
    calc(i)
}

您有两种专门的方法分别采用IntDouble。您的值类型为Number超类型IntDouble)。虽然i显然是一个整数,但您的变量的类型为Number,它不能是calc(i: Int)calc(d: Double)的参数。

在你的情况下,你得到一个Response并且想要调用其中一个重载方法,其中没有一个直接使用Response