我正在尝试创建一个系统,其中协议(或抽象类)的实现可以满足该协议的最低要求,但仍可以访问提供的解决方案随附的独特功能。让我用一个例子来说明:
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
}
}
现在要破解这个问题,我一直在研究泛型和泛型函数,但是我还没有想出能以表达方式起作用的东西。
我应该注意,我的实现必须满足多个要求。我可以通过在协议上使用泛型来完成这项工作。
interface Animal<T: Food, B: Behaviour>
这可以工作,但是由于有多个要求,它很快看起来很荒谬,我觉得我缺少了一些东西。除非在下一个示例中缺少某些内容,否则属性的泛型将不起作用。
// Protocol
val <T> favoriteFood: <T: Food>
// Implementation (ideally, but wouldn't work like that I guess)
override val favoriteFood: Banana = Banana()
然后我的改良方法看上去也不是那么漂亮:
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()
}
}
在这一点上,我不确定我是否看不到该怎么做或是否不可能。感觉这是有可能的,我想知道是否有人可以为我指出正确的解决方法。
或者也许它甚至与我想做的事情都没有道理,但即使我也想听,因为它对我所设想的设置确实有意义。
谢谢。
在首次回复后进行编辑: 我打算在构建阶段之外也访问favouriteFood。 将可变的favouriteFood转换为val,因为它更适合目标。
答案 0 :(得分:1)
只要在构造时只尝试访问favoriteFood
,这还不错:
class Monkey: Animal {
override var favoriteFood: Food? // no initializer here
init {
val food = Banana()
favoriteFood = food
food.peel()
}
}
如果您不将自己限制在init
节和其他构造时操作中,那么您尝试做的事情将从根本上被破坏。
val animal: Animal = Monkey()
animal.favoriteFood = Orange() // favoriteFood is a var, so it's publicly modifiable
animal.something() // can't assume favoriteFood is a Banana!
您可以将favoriteFood
改成val
,这会有所帮助。但是您不能从favoriteFood
中的类型之外使Food
可变,并尝试限制子类型中favoriteFood
的类型。