如何将 "join" sub 类 转换为超类型实例?

How to "join" sub classes into a super type instance?

如果我有一个接收 Callback 作为参数的函数,我如何使用 "collection" 或 "group" of sub-class/derived-class of Callback 这样,根据收到的参数,我可以 enable/disable 某些功能,如果收到 sub-class/derived-class "has" 或 "matches" 功能?

例如

import kotlin.random.Random

interface Callback

interface FruitsCallback : Callback {
    fun onFruitsDeleted(ignored: Int)
}

interface VegetablesCallback : Callback {
    fun onVegetablesDeleted(ignored: Int)
}

class FruitsStore : FruitsCallback {

    override fun onFruitsDeleted(ignored: Int) {
        throw NotImplementedError()
    }
}

class VegetablesStore : VegetablesCallback {

    override fun onVegetablesDeleted(ignored: Int) {
        throw NotImplementedError()
    }
}

fun delete(callback: Callback) {

    if (callback is FruitsCallback) {
        // Delete 5 fruits
        callback.onFruitsDeleted(5)
    }

    if (callback is VegetablesCallback) {
        // Delete 7 vegetables
        callback.onVegetablesDeleted(7)
    }
}

fun main() {

    val fruitsStore = FruitsStore()
    val vegetablesStore = VegetablesStore()

    val callback: Callback = if (Random.nextBoolean()) {
        fruitsStore + vegetablesStore
    } else fruitsStore

    delete(callback)
}

当我尝试执行 fruitsStore + vegetablesStore 时,错误出现在 main() 方法中。这显示类型不匹配问题。关于 kotlin 的 .plus().

可以做些什么

但是,在使用 coroutines 时,如何将以下类型添加在一起?

val exceptionHandler = CoroutineExceptionHandler { context, throwable -> println("$throwable") }
val coroutineContext = Dispatchers.Main + SupervisorJob() + exceptionHandler

我想知道 coroutineContext 如何能够接收一组这些类型的实例并将它们表示为一个。

我对科特林还很陌生。请解释:

协程 API 使用 operator overloading+ 运算符做一些它通常不能做的事情。如果您查看源代码,重载的加运算符的函数实例化了一个新的 CoroutineContext,它复制了两个操作数的属性值。

在您的情况下,要实现此功能,您必须编写自己的运算符函数。但是尝试有条件地实现多个接口很快就会变得非常复杂。在您的示例中,只有两种可能的回调类型,并且已经构成了具有三个分支的长函数:

operator fun Callback.plus(other: Callback): Callback {
    val callbacks = listOf(this, other)
    return when {
        callbacks.all { it is FruitsCallback } -> object: FruitsCallback {
                override fun onFruitsDeleted(ignored: Int) {
                    callbacks.forEach { (it as FruitsCallback).onFruitsDeleted(ignored) }
                }
            }

        callbacks.all { it is VegetablesCallback } -> object : VegetablesCallback {
                override fun onVegetablesDeleted(ignored: Int) {
                    callbacks.forEach { (it as VegetablesCallback).onVegetablesDeleted(ignored) }
                }
            }

        else -> object: FruitsCallback, VegetablesCallback {
            override fun onFruitsDeleted(ignored: Int) {
                callbacks.forEach { (it as? FruitsCallback)?.onFruitsDeleted(ignored) }
            }

            override fun onVegetablesDeleted(ignored: Int) {
                callbacks.forEach { (it as? VegetablesCallback)?.onVegetablesDeleted(ignored) }
            }
        }
    }
}

如果Callback有第三种实现,上面的函数就会有七个分支。而且这里没有强制你如果添加额外的实现记得更新这个函数。

也就是说,您的 delete() 函数版本使用 is 是一种代码味道,未能利用多态性。在这种情况下,最好将 delete() 作为函数添加到 Callback 中,并且每个实现都可以自行定义其含义。