Generics Kotlin中协议实现可识别的推断类型
我正在尝试创建一个系统,其中协议(或抽象类)的实现满足该协议的最低要求,但仍然可以访问提供的解决方案附带的独特功能。让我举例说明:Generics Kotlin中协议实现可识别的推断类型,generics,kotlin,reification,inferred-type,Generics,Kotlin,Reification,Inferred Type,我正在尝试创建一个系统,其中协议(或抽象类)的实现满足该协议的最低要求,但仍然可以访问提供的解决方案附带的独特功能。让我举例说明: interface Food interface Animal { val favoriteFood: Food } class Banana: Food { fun peel() { print("Banana peeled") } } class Monkey: Animal { override val fa
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()
//协议
val Favorite食品:
//实现(理想情况下,但我想不会像那样工作)
覆盖val favoriteFood:香蕉=香蕉()
那么我的物化方法看起来也不那么漂亮:
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()
}
}
开放类动物{
//这最好是私人的,以防止不正确的使用
var favoriteFood:Food?=null
娱乐登记处免费食品(食品:食品){
喜欢的食物
}
//这可能甚至不需要内联+具体化
内联乐趣getFavoriteFood():T{
//当然,我们需要验证favoriteFood是否匹配T
将最喜欢的食物作为食物返回
}
}
猴子类:动物(){
初始化{
注册方便食品(香蕉())
getFavoriteFood().peel()
}
}
在这一点上,我不能完全确定我是否看不到如何做,或者这是否是不可能的。但我觉得这是可能的,我想知道你们中是否有人能为我指出解决问题的正确方向
或者,我想做的事情可能没有意义,但即使是我想听的,因为这对我所设想的设置是有意义的
提前谢谢
第一次响应后编辑:
我也打算在施工阶段之后获得favoriteFood。
将可变的favoriteFood转换为val,因为这更符合目标。只要您在构建时只尝试访问
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
,这会有所帮助。但是,您不能在食品
中从类型外部使偏好食品
可变,并尝试在子类型中限制偏好食品
的类型。谢谢您的快速回答。在我的情况下,我会访问它后建设以及。关于不可变状态的观点很好,因为这正是我想要的。我会将其作为编辑评论添加到原始帖子中。目标是通过在子类型中提供更复杂的变体来实现最低协议要求,但仍然可以通过其协议访问器识别为复杂变体。在这个主题上,我一直在看斯威夫特的associatedtype,因为我觉得这暗示了我所寻求的:在这种情况下,听起来您确实需要泛型类型参数,在这种情况下,它应该看起来像类动物{val favoriteFood:F}
。不需要强制转换或类似操作,但您必须接受额外的类型参数。