I have a several classes I don't control, upon which I've already created several identically-named extension methods across several common "attributes". The identically-named extension functions always return the same value type, though calculated in different ways for each type of receiver. Here is a simplified example based on built-in types for just one attribute:
// **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}")
}
Imagine several other "common" properties extended in the same manner as .len in some classes I don't control. If I don't want to repeat myself in every class, how do I construct a properly typed class that can operate on .len (and other such properties) generically for these three classes?
I've researched the following but not found workable solutions yet:
- generics, in the example above, but can't get the syntax right.
- sealed classes, but I don't have control of these classes.
- union types, which I've found aren't supported in Kotlin.
- wrapper classes, but couldn't get the syntax right.
- passing lambdas a la this blog explanation, but didn't get it right, and it seemed boptimalsu to pass multiple lambdas around for every method.
There must be a better way, right?