Kotlin拓展函数的多态性

我有几个类我不控制 ,我已经创建了几个同名的扩展方法跨几个常见的“属性”。 相同名称的扩展函数总是返回相同的值types,尽管对于每种types的接收器以不同的方式进行计算。 下面是一个基于内置types的简单例子,只有一个属性:

// **DOES NOT COMPILE** // three sample classes I don't control extended for .len inline val String.len get() = length inline val  List.len get() = size inline val  Sequence.len get() = count() // another class which needs to act on things with .len class Calc(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) { 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(以及其他这样的属性)上对这三个类进行一般操作的正确types的类呢?

我已经研究了以下但尚未find可行的解决方案:

  • generics,在上面的例子中, 但不能得到正确的语法。
  • 封闭类, 但我没有这些类的控制。
  • 我发现的联合types在Kotlin中不被支持。
  • 包装类, 但不能得到正确的语法。
  • 把这个博客的解释传给lambda, 但是没有得到正确的 答案 , 而且似乎为每种方法都传递了多个lambdaexpression式。

一定有更好的办法吧?

下面是一个密封类和一个扩展属性的例子,可以将任何东西转换成可以给你lendouble 。 不知道它是否有更好的可读性。

 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(val l: List): Calc() { override val len: Int? get() = l.size } class CalcSequense(val s: Sequence): Calc() { override val len: Int? get() = s.count() } object None: Calc() { override val len: Int? get() = null } } fun main(args: Array) { 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}") }