I'm trying to create a system where implementations of a protocol (or abstract class) fulfill the minimum requirements of that protocol, but still has access to the unique functionality that come with the provided solution. Let me illustrate with an example:
interface Food
interface Animal {
val favoriteFood: Food
}
class Banana: Food {
fun peel() {
print("Banana peeled")
}
}
class Monkey: Animal {
override val favoriteFood: Food = Banana()
init {
favoriteFood.peel() // Doesn't work as type is Food, not Banana
}
}
Now to crack this I've been looking into generics and reified functions, but I haven't been able to come up with something that works in an expressive way.
I should note that my implementations would have to fulfill more than one requirement. I could make that work by using generics on the protocol.
interface Animal<T: Food, B: Behaviour>
This would work, but with multiple requirements it quickly looks ridiculous and I feel I'm missing something. Generics on properties don't work, unless I'm missing something in the next example.:
// Protocol
val <T> favoriteFood: <T: Food>
// Implementation (ideally, but wouldn't work like that I guess)
override val favoriteFood: Banana = Banana()
Then my reified approach doesn't look that pretty either:
open class Animal {
// This should ideally be private to prevent incorrect use
var favoriteFood: Food? = null
fun registerFavoriteFood(food: Food) {
favoriteFood = food
}
// This probably doesn't even have to be inline+reified
inline fun <reified T> getFavoriteFood() : T {
// Of course we need to validate if favoriteFood matches T
return favoriteFood as T
}
}
class Monkey: Animal() {
init {
registerFavoriteFood(Banana())
getFavoriteFood<Banana>().peel()
}
}
At this point I'm not fully sure whether I don't see how to do it, or whether it's not possible. It feels like it's possible though and I wonder if any of you can point me in the right direction on how to solve it.
Or maybe it doesn't even make sense what I'm trying to do, but even that I'd like to hear, as it does make sense for the setup I envision.
Thanks in advance.
Edit after first response: I intend to access favoriteFood beyond the construction phase as well. Turned the mutable favoriteFood into a val as that better fits the goal.