Mark
05/02/2024, 4:00 AMinterface Foo {
// withBar always returns same type as `this`
fun withBar(bar: Bar): Foo
}
class SubFoo(val bar: Bar? = null): Foo {
override fun withBar(bar: Bar): SubFoo = SubFoo(bar)
}
Full code in threadMark
05/02/2024, 4:00 AMclass Bar
interface Foo {
// withBar always returns same type as `this`
fun withBar(bar: Bar): Foo
}
class SubFoo(val bar: Bar? = null): Foo {
override fun withBar(bar: Bar): SubFoo = SubFoo(bar)
}
// will not compile: Type mismatch
// fun <F: Foo> List<F>.mapFoos(bar: Bar): List<F> = this.map { foo ->
// foo.withBar(bar)
// }
// alternative approach which seems to work
fun <F: Foo> List<F>.mapFoos(bar: Bar, withBar: (F, Bar) -> F): List<F> = this.map { foo ->
withBar(foo, bar)
}
// convenience for when don't care about sub type. In this case
// wouldn't need to use mapFoos because of mapFoos simple
// implementation, but imagine mapFoos is much more complex.
fun List<Foo>.mapFoos(bar: Bar): List<Foo> = mapFoos(bar, Foo::withBar)
fun main() {
val subFoo = SubFoo()
val bar = Bar()
val mappedSubFoo = listOf(subFoo).mapFoos(bar, SubFoo::withBar) // List<SubFoo>
}
Mark
05/02/2024, 4:00 AMRuckus
05/02/2024, 5:26 AMMark
05/02/2024, 5:39 AMWout Werkman
05/02/2024, 6:23 AMSelf
. But the only way to model this in Kotlin is with Generics.
One such example is Comparable
, which practically contains a function: compare(other: Self): Int
. But since Java too did not have Self
, Comparable
takes a generic argument as a workaround.