通过动态调度委托派生类方法

时间:2017-12-17 17:44:03

标签: kotlin

鉴于以下场景,有一些基类应该简单地委托给派生类,为什么派生类中的两个apply()方法永远不会被调用?

要演示:在main函数中,我将使用两个事件调用apply。在抽象类中,我将apply这两个事件。基类中有一个通用的apply(Event)函数,但应该忽略它,并通过动态调度转到派生类中的各个apply(EventOne)apply(EventTwo)方法。

我也尝试过这种方法,每个apply方法返回自己,applyFromHistory函数使用fold代替,但结果相同。

fun main(args: Array<String>) {
    val subject = SomeAggregate()

    subject.applyFromHistory(listOf(
        EventOne(123),
        EventTwo("foobar")
    ))
}

sealed class Event
data class EventOne(val id: Int) : Event()
data class EventTwo(val content: String) : Event()

abstract class AggregateRoot(
    private val events : MutableList<Event> = mutableListOf()
) {

    fun applyFromHistory(history: List<Event>) {
        history.forEach { apply(it) }
    }

    fun apply(event: Event) { /* does nothing */ }
}

class SomeAggregate(var id: Int = 0, var content: String = "") : AggregateRoot() {
    fun apply(event: EventOne) {
        id = event.id
    }

    fun apply(event: EventTwo) {
        content = event.content
    }
}

我希望离开:

abstract class AggregateRoot(... {

   ...

   abstract fun apply(event: Event)
}

class SomeAggregate(... : AggregateRoot() {

   ...

   override fun apply(event: Event) {
       when(event) {
           is EventOne -> apply(event)
           is EventTwo -> apply(event)
       }
   }

   ...
}

1 个答案:

答案 0 :(得分:2)

因为动态调度仅适用于this,即方法覆盖。它不适用于方法的参数;方法重载在编译时静态解析。

您遇到的问题传统上是通过visitor pattern等问题解决的。另一种方法是根据参数的运行时类型执行查找,Kotlin允许您通过when expression更优雅地执行查找。