Intereting Posts
Mapbox OfflineRegionObserver прослушиватель unregister содержание в параметре основного развлечения в котлине IntArray vs Array <Int> в Котлине Список файлов рекурсивно в Котлине В Kotlin почему аргумент по умолчанию не передается после того, как функция назначается переменной? Почему компилятор Scala дает мне ошибку при передаче закрытого класса Kotlin в конструктор? Установите маркер времени выполнения для любого вида с помощью Kotlin При использовании сопрограмм kotlin, как я могу тестировать функцию, вызывающую функцию приостановки? Класс данных Kotlin для JSON с пружиной / jackson Котлин и Даггер2 Android Studio 3.0 Kotlin не работает должным образом Нет аргументов типа, ожидаемых для fun findViewById (p0: Int): View Как объявить параметр как функцию без возвращаемого значения? Предупреждение компилятора при использовании аннотации @Value в проекте Kotlin Могут ли функции расширения быть вызваны «статическим» способом?

Полиморфизм на функциях расширения в Котлине

У меня есть несколько классов, которые я не контролирую , на которых я уже создал несколько одинаково названных методов расширения в нескольких общих «атрибутах». Идентифицированные функции расширения всегда возвращают один и тот же тип значения, хотя и рассчитаны по-разному для каждого типа приемника. Ниже приведен упрощенный пример, основанный на встроенных типах только для одного атрибута:

// **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 (и другими такими свойствами) в общем случае для этих трех классов?

Я изучил следующие, но не нашел работоспособных решений:

  • generics, в приведенном выше примере, но не может получить синтаксис правильно.
  • запечатанных классов, но я не контролирую эти классы.
  • типы соединений, которые я нашел, не поддерживаются в Котлине.
  • классов оболочки, но не смог получить синтаксис правильно.
  • пропуская lambdas a la это объяснение в блоге , но не получилось правильно, и казалось, что boptimalsu пропускает несколько лямбда вокруг каждого метода.

Должен быть лучший способ, не так ли?

    Вот пример с закрытыми классами и одним свойством расширения, чтобы преобразовать что-либо в нечто, что может дать вам 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}") }