Is there a way to model this? ```interface Foo { ...
# getting-started
m
Is there a way to model this?
Copy code
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)
}
Full code in thread
Copy code
class 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>
}
r
m
Ah, yes I’ve used this technique in the past. But I really don’t like it. Making Foo generic just clutters the code IMO.
👍 1
w
Some other languages do have a language feature for this, such as Swift, who calls this
Self
. 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.
👍 3