I’m trying to learn more about generics. I current...
# announcements
I’m trying to learn more about generics. I currently have
Copy code
interface Id

inline class BarId(val value: Int): Id
inline class BazId(val value: Int): Id

sealed class Foo<T: Id> {
   abstract val id: T
   data class Bar(...): Foo<BarId>()
   data class Baz(...): Foo<BazId>()

fun <T: Foo<U>, U: Id> myFun(entity: T): U = TODO()
Suppose I need to add a function to
that will take an Id param and spit back out a child class (the one that is affiliated with the Id implementation in question). So
should take
and spit out
. For example.
Copy code
sealed class Foo<T: Id> {
   abstract fun <T: Foo<U>, U: Id> changeId(id: U): T
I’m sitting here with
Copy code
data class Bar(...): Foo<BarId>() {
   override fun changeId(id: BarId): Bar = TODO()
not really knowing what to put for
. Obviously the implementation is going to be
changeId(id: BarId): Bar = this(id=id)
but I have to put some generics in the signature somewhere or else compiler/linter tells me this does not match the signature of Foo.changeId, which it is intended to override.
Since Bar and Baz are data classes, you can just use the
method to create a new instance with a different ID. Maybe you simplified your use-case before posting here, so not sure this will actually work for your real world purposes.
Also, this is pretty nasty, but it works
Copy code
sealed class Foo<U : Id, S : Foo<U, S>> {
    abstract val id: U
    abstract fun changeId(id: U): S

    data class Bar(override val id: BarId) : Foo<BarId, Bar>() {
        override fun changeId(id: BarId): Bar = this.copy(id = id)

    data class Baz(override val id: BazId) : Foo<BazId, Baz>() {
        override fun changeId(id: BazId): Baz = this.copy(id = id)
👍 1
is what I was using, but I omitted it so my question wouldn’t push potential answers in the direction I’d (possibly suboptimally) chosen. My issue was more around how to keep using the generics. I didn’t realize that I could reuse the class generic param in the function without re-declaring a generic in the function header itself. Problem solved, thanks!
Yeah.. that type of “recursive generics” (not sure if that’s a proper name, just what it looks like to me) is a bit odd.. but can help define a “self” type