gpt4 book ai didi

generics - Kotlin 中扩展函数的多态性

转载 作者:行者123 更新时间:2023-12-02 01:06:34 24 4
gpt4 key购买 nike

我有几个我无法控制的类(class) ,在此基础上,我已经在几个常见的“属性”中创建了几个同名的扩展方法。同名扩展函数总是返回相同的值类型,尽管对于每种类型的接收器以不同的方式计算。这是 简化 仅基于一个属性的内置类型的示例:

// **DOES NOT COMPILE**

// three sample classes I don't control extended for .len
inline val String.len get() = length
inline val <T> List<T>.len get() = size
inline val <T> Sequence<T>.len get() = count()

// another class which needs to act on things with .len
class Calc<T>(val obj:T) { // HERE IS THE PROBLEM...
val dbl get() = obj?.len * 2 // dummy property that doubles len
// ... and other methods that use .len and other parallel extensions
}

fun main(a:Array<String>) {
val s = "abc"
val l = listOf(5,6,7)
val q = (10..20 step 2).asSequence()
val cs = Calc(s)
val cl = Calc(l)
val cq = Calc(q)
println("Lens: ${cs.dbl}, ${cl.dbl}, ${cq.dbl}")
}

想象一下,在我无法控制的某些类中,以与 .len 相同的方式扩展了其他几个“通用”属性。如果我不想每堂课都重复自己, 如何为这三个类构建一个可以在 .len (和其他此类属性)上进行操作的正确类型的类?

我研究了以下但尚未找到可行的解决方案:
  • 泛型,在上面的示例中,但无法正确获取语法。
  • 密封类,但我无法控制这些类。
  • 我发现 Kotlin 不支持联合类型。
  • 包装
    类,但无法正确使用语法。
  • 通过 lambdas a la
    this blog explanation ,但没有得到正确的结果,并且似乎最好为每种方法传递多个 lambda。

  • 应该有更好的方法吧?

    最佳答案

    这是一个带有密封类和单个扩展属性的示例,可以将任何东西转换为可以给你len的东西。或 double .不确定它是否具有更好的可读性。

    val Any?.calc get() = when(this) {
    is String -> Calc.CalcString(this)
    is List<*> -> Calc.CalcList(this)
    is Sequence<*> -> Calc.CalcSequense(this)
    else -> Calc.None
    }

    /* or alternatively without default fallback */

    val String.calc get() = Calc.CalcString(this)
    val List<*>.calc get() = Calc.CalcList(this)
    val Sequence<*>.calc get() = Calc.CalcSequense(this)

    /* sealed extension classes */

    sealed class Calc {

    abstract val len: Int?

    val dbl: Int? by lazy(LazyThreadSafetyMode.NONE) { len?.let { it * 2 } }

    class CalcString(val s: String): Calc() {
    override val len: Int? get() = s.length
    }

    class CalcList<out T>(val l: List<T>): Calc() {
    override val len: Int? get() = l.size
    }

    class CalcSequense<out T>(val s: Sequence<T>): Calc() {
    override val len: Int? get() = s.count()
    }

    object None: Calc() {
    override val len: Int? get() = null
    }

    }

    fun main(args: Array<String>) {
    val s = "abc".calc
    val l = listOf(5,6,7).calc
    val q = (10..20 step 2).asSequence().calc

    println("Lens: ${s.dbl}, ${l.dbl}, ${q.dbl}")
    }

    关于generics - Kotlin 中扩展函数的多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47275163/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com