为什么通用超类型声明不允许引用子类型对象?
Why Does a Generic Supertype Declaration Not Permit Referencing to Subtype Objects?
我想知道为什么泛型超类型参数不允许引用子类型对象的背景。
abstract class Pet()
class Cat: Pet()
interface Retailer<T> {
fun sell(): T
}
class CatRetailer: Retailer<Cat> {
override fun sell(): Cat {
println("Sell Cat")
return Cat()
}
}
// Type MismatchError prior to compilation
val steveIrwinTheAnimalEnslaver: Retailer<Pet> = CatRetailer()
变量定义导致类型不匹配错误,其中编译器需要类型 Retailer<Pet>
。
但是,Pet
是 Cat
的超类型。为什么多态性不像下面那样工作?
open class SuperClassName() {}
class SubClassName : SuperClassName()
var variableName: SuperClassName = SubClassName()
您写道:
class CatRetailer: Retailer<Cat>
为了使代码工作,您需要编写:
class CatRetailer: Retailer<Pet>
猫零售商没有实现宠物的接口,它实现了猫的接口。如果它会实现 pet 的接口,你可以这样写:
val steveIrwinTheAnimalEnslaver: Retailer<Pet>
在实现 cat 的接口时,您是在说您的零售商是 cat 类型并且只有 cat。
Cat 类型的接口 没有 extend/implement Pet 类型的接口。
您给出的子类化示例不是这种情况。
总结一下:即使 B 扩展了 A,Interface<B>
也不是 interface<A>
。
但是B就是A。
我希望你已经足够清楚了。
Pet
是 Cat
的超类型,但 Retailer<Pet>
是 而不是 Retailer<Cat>
的超类型。看看为什么想象你添加了一个方法:
abstract class Pet()
class Cat: Pet()
class Dog: Pet()
interface Retailer<T> {
fun sell(): T
fun buy(x: T): Unit
}
// only really knows how to buy cats
val steveIrwinTheAnimalEnslaver: Retailer<Pet> = CatRetailer()
// legal for any Retailer<Pet>
steveIrwinTheAnimalEnslaver.buy(Dog())
在这种情况下,您的选择是:
使用 Retailer<out Pet>
,它不允许调用像 buy
和 "consume" T
这样的成员。你可以把它想象成Retailer<any subtype of Pet>
,你不会错的。还有双重 Retailer<in Pet>
允许调用 buy
但不允许调用 sell
.
Declare interface Retailer<out T>
不允许 declaring buy
并且意味着“如果 A
是 [=25 的子类型=],则 Retailer<A>
是 Retailer<B>
的子类型。
我想知道为什么泛型超类型参数不允许引用子类型对象的背景。
abstract class Pet()
class Cat: Pet()
interface Retailer<T> {
fun sell(): T
}
class CatRetailer: Retailer<Cat> {
override fun sell(): Cat {
println("Sell Cat")
return Cat()
}
}
// Type MismatchError prior to compilation
val steveIrwinTheAnimalEnslaver: Retailer<Pet> = CatRetailer()
变量定义导致类型不匹配错误,其中编译器需要类型 Retailer<Pet>
。
但是,Pet
是 Cat
的超类型。为什么多态性不像下面那样工作?
open class SuperClassName() {}
class SubClassName : SuperClassName()
var variableName: SuperClassName = SubClassName()
您写道:
class CatRetailer: Retailer<Cat>
为了使代码工作,您需要编写:
class CatRetailer: Retailer<Pet>
猫零售商没有实现宠物的接口,它实现了猫的接口。如果它会实现 pet 的接口,你可以这样写:
val steveIrwinTheAnimalEnslaver: Retailer<Pet>
在实现 cat 的接口时,您是在说您的零售商是 cat 类型并且只有 cat。
Cat 类型的接口 没有 extend/implement Pet 类型的接口。
您给出的子类化示例不是这种情况。
总结一下:即使 B 扩展了 A,Interface<B>
也不是 interface<A>
。
但是B就是A。
我希望你已经足够清楚了。
Pet
是 Cat
的超类型,但 Retailer<Pet>
是 而不是 Retailer<Cat>
的超类型。看看为什么想象你添加了一个方法:
abstract class Pet()
class Cat: Pet()
class Dog: Pet()
interface Retailer<T> {
fun sell(): T
fun buy(x: T): Unit
}
// only really knows how to buy cats
val steveIrwinTheAnimalEnslaver: Retailer<Pet> = CatRetailer()
// legal for any Retailer<Pet>
steveIrwinTheAnimalEnslaver.buy(Dog())
在这种情况下,您的选择是:
使用
Retailer<out Pet>
,它不允许调用像buy
和 "consume"T
这样的成员。你可以把它想象成Retailer<any subtype of Pet>
,你不会错的。还有双重Retailer<in Pet>
允许调用buy
但不允许调用sell
.Declare
interface Retailer<out T>
不允许 declaringbuy
并且意味着“如果A
是 [=25 的子类型=],则Retailer<A>
是Retailer<B>
的子类型。