David Kubecka
01/18/2023, 2:22 PMclass Cat : Animal {
override var owner: CatOwner
override fun switchOwner(owner: AnimalOwner) {
owner = owner as CatOwner
}
}
The cast to CatOwner
is semantically redundant because it's quite clear what the resulting type should be, only the compiler can't/shouldn't guess it. Still, these casts soon seem like a boilerplate (especially with more complex generic types) so I devised the following helper function:
inline fun <reified TOut : T, T : Any> T.asTOut() = this as TOut
The usage would then simply be
override fun switchOwner(owner: AnimalOwner) {
owner = owner.asTOut()
}
This basically emulates what the compiler does when inferring generic parameter types. Of course, the difference in my example is that it's generally unsafe (that's why the compiler doesn't do it automatically).
What do you think about this? Neat or horrible?Sam
01/18/2023, 2:27 PMKlitos Kyriacou
01/18/2023, 2:51 PMSam
01/18/2023, 2:53 PMKlitos Kyriacou
01/18/2023, 2:54 PMDavid Kubecka
01/18/2023, 3:02 PMephemient
01/18/2023, 3:05 PMinterface Animal<A : Animal<A, O>, O : Owner<O, A>> {
var owner: O
}
interface Owner<O : Owner<O, A>, A : Animal<A, O>>
class Cat : Animal<Cat, CatOwner> {
override var owner = CatOwner()
}
class CatOwner : Owner<CatOwner, Cat>
may be overkill depending on the use case, but this forbids Cat().owner = notCatOwner()
at compile time instead of a runtime castDavid Kubecka
01/18/2023, 3:07 PM