kyleg
01/02/2020, 9:07 PMinterface 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 Foo
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 myBar.changeId
should take BarId
and spit out Bar
. For example.
sealed class Foo<T: Id> {
...
abstract fun <T: Foo<U>, U: Id> changeId(id: U): T
}
I’m sitting here with
data class Bar(...): Foo<BarId>() {
override fun changeId(id: BarId): Bar = TODO()
}
not really knowing what to put for changeId
. 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.StavFX
01/03/2020, 12:16 AMcopy
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.StavFX
01/03/2020, 12:25 AMsealed 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)
}
}
kyleg
01/03/2020, 5:39 AMcopy
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!StavFX
01/03/2020, 6:32 PM