为何可在协变类型List中传入逆变参数?Kotlin泛型疑问
为什么逆变类型参数I能传入协变的List中?
先明确两个核心类型概念:
- 协变(out):比如
List<out E>,若A是B的子类,List<A>可直接当作List<B>使用——相当于对外输出的类型可以更具体。 - 逆变(in):比如
ListMapper<in I>,若A是B的子类,ListMapper<B, O>可直接当作ListMapper<A, O>使用——相当于对内接收的类型可以更宽泛。
结合你的代码来拆解:
1. List的协变特性
List<out E>的协变意味着:如果I1是I2的子类,那么List<I1>是List<I2>的子类型。比如Dog继承自Animal,List<Dog>可以赋值给List<Animal>。
2. ListMapper中I的逆变要求
ListMapper<in I, out O>的逆变要求:如果I1是I2的子类,ListMapper<I2, O>必须能适配成ListMapper<I1, O>。
3. 两者的兼容性匹配
你的ListMapper继承自Mapper<List<I>, List<O>>,这里隐含了Mapper的第一个类型参数(输入类型)是逆变的(类似Kotlin标准库Function1<in P, out R>的输入参数P)。
当I是逆变类型时,List<I>作为Mapper的输入类型,刚好满足兼容性:
- 假设
I2是I1的父类,ListMapper<I2, O>对应Mapper<List<I2>, List<O>> - 因为List是协变的,
List<I1>是List<I2>的子类型 - 而
Mapper的输入参数是逆变的,所以Mapper<List<I2>, List<O>>可以适配成Mapper<List<I1>, List<O>>,也就是ListMapper<I2, O>可以适配成ListMapper<I1, O>——完全符合I的逆变要求。
简单说,I的逆变和List的协变在这里是互补的,刚好满足整个类型体系的兼容性规则,所以这种写法是合法的。
内容的提问来源于stack exchange,提问作者Omar Redani
相关产品推荐
相关产品推荐

