本文最后更新于 786 天前
1. 子类型
任何时候,如果要使用 类型A 的值,都能用 类型B 的值作为替换(当做 A 的值),称 B 是 A 的子类型。
2. 泛型中的子类型
如果List
1. List
2. List
// List带泛型的定义
public interface List<E> extends Collection<E> {
boolean add(E e);
E get(int index);
}
// List<String>定义如下:
public interface List<String> extends Collection<String> {
boolean add(String e);
String get(int index);
}
// List<CharSequence>定义如下:
public interface List<CharSequence> extends Collection<String> {
boolean add(CharSequence e);
CharSequence get(int index);
}
虽然String get(int index);返回值的范围比CharSequence get(int index);小,满足了第二个条件。
但boolean add(String e);接收参数的范围明显比boolean add(CharSequence e);要小,不满足第一个条件。不变型
所以List
不变型:Type1是Type2的子类,如果A
和A 不存在父子关系,则称 类A 在类型参数上是不变型的 协变: 当类型参数变得更具体时,类也变得更具体。当类型参数变得更抽象时,类也变得更抽象
即将上述的add/set方法屏蔽 只能get/取返回值,kotlin使用out关键词class MyList<out T>{ ... }
逆变: 当类型参数变得更具体时,类却变得更抽象。当类型参数变得更抽象时,类却变得更具体
即将上述的get/取返回值屏蔽,保留add/set方法,kotlin使用in关键词class MyList<in T>{ ... }
Java成为PECS原则,协变:<? extends T>, 逆变:<? super T>
kotlin则POCI原则
3. 投影
投影类型 | 投影实例 | 变型 | 继承关系 | 限制 |
---|---|---|---|---|
out投影 | Group< out Animal > | 协变 | Group< Dog > 是 Group< out Animal > | 子类类型参数不能作为方法参数 |
in投影 | Group< in Animal > | 逆变 | Group< in Animal > 是 Group< Dog > | 子类类型参数不能作为方法返回值 |
star投影 | Group< * > | — | Group<任何类型 > 都是 Group< * > | 子类类型参数不能做方法参数也不能做返回值 |