gpt4 book ai didi

generics - Kotlin 中的 "Bidirectional"类型投影/方差?

转载 作者:行者123 更新时间:2023-12-02 13:21:12 28 4
gpt4 key购买 nike

假设我们有一个像 Pug : Dog : Mammal : Animal 这样的类层次结构。 .

我想要一个接受 Bag<T> 的函数(其中 BagT 中是不变的)作为 Dog 的子或父类(super class)的事物的参数:fun work(things: Bag<in/out Dog)这样 Bag<Animal> , Bag<Dog> , Bag<Pug>可以,但是 Bag<Cat>不被接受。

老实说,我什至不确定这种类型的投影叫什么。任何指针?

最佳答案

如果你想想inout修饰符真正的意思是,你很快就会意识到拥有 in OR out真的没有意义。

一起来看看out第一的。有<out T>并不意味着“此函数接受 T 及其子类作为参数”。它实际上意味着“这个函数不会做任何类 T 的参数或其任何子类不能做的事情”。 此修饰符对您可以对该参数执行的操作施加了限制。

检查此代码:

fun doThingsWithBag(bag: Bag<out Dog>) {
bag.getAny().walk() // allowed

bag.put(Dog()) // not allowed
}

你不能把任何狗放进这个袋子里,因为这个袋子实际上可能是一个类型 Bag<Pug> , 和 Bag<Pug>不接受随机的 Dog .
in 也是如此。 . <in T>并不意味着“此函数接受 T 及其 super 函数”。它更像是“这个函数不会做任何事情 T 或者它的任何父类(super class)都不能做”。
fun doThingsWithBag(bag: Bag<in Dog>) {
bag.put(Dog()) // allowed

bag.getAny().walk() // not allowed
}

现在你可以把狗放在包里,但你不能对包里的狗做任何事情,因为包实际上可能是 Bag<Animal>并且不能保证你从包里拿出的“东西”是 Dog .

如您所见, in 之间有明显的区别。和 out可以,因此它们不能共存。

即使是其他答案中建议的界面也对您没有太大帮助,因为您的 Animal类还需要实现相同的接口(interface),这意味着 Cat也可以访问该界面。唯一的解决方法是让您的 work接受方法 Bag<Any>并手动检查其泛型类。

更新:

您尝试做的事情在 OOP 中是不可能的。您正在寻找的基本上是这样的:
update(Animal()) // allowed
update(Dog()) // allowed
update(Pug()) // allowed
update(Cat()) // not allowed (compile time error)

但是,编译器无法阻止您这样做:
val animal: Animal = Cat()
update(animal) // ???

通过手动检查输入类型,您只能在运行时执行类似的操作。

关于generics - Kotlin 中的 "Bidirectional"类型投影/方差?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56386133/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com