Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics Kotlin中协议实现可识别的推断类型_Generics_Kotlin_Reification_Inferred Type - Fatal编程技术网

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}
。不需要强制转换或类似操作,但您必须接受额外的类型参数。