tcga癌症亚型获取
Java 5已将通用多态性引入Java生态系统。 即使我们都知道由于泛型类型擦除及其后果而引起的无数警告,这还是对Java语言的重要补充。 通用多态性(也称为参数多态性 )通常与可能预先存在的亚型多态性正交。 一个简单的例子是collections API
List<? extends Number> c = new ArrayList<Integer>();
在上面的示例中,子类型ArrayList
被分配给超类型List
的变量。 同时,使用Integer
类型对ArrayList
进行参数化,可以将其分配给兼容的参数超类型? extends Number
? extends Number
。 在通用多态性的情况下,这种子类型多态性的用法也称为协方差 ,尽管当然也可以在非通用上下文中实现协方差。
具有通用多态性的协方差
协方差对于泛型很重要。 它允许创建复杂的类型系统。 简单的示例涉及将协方差与通用方法结合使用:
<E extends Serializable> void serialize(Collection<E> collection) {}
上面的示例接受任何Collection
类型,可以在调用站点使用诸如List
, ArrayList
, Set
等类型对它进行子类型化。 同时,仅要求调用站点上的泛型类型参数是Serializable
的子类型。 即它可以是List<Integer>
或ArrayList<String>
等。
将亚型多态性与通用多态性相关联
于是人们常常被引诱去关联两种正交类型的多态性。 这种相关性的一个简单示例是将IntegerList
或StringSet
专门IntegerList
:
class IntegerList extends ArrayList<Integer> {}
class StringSet extends HashSet<String> {}
这是很容易看到明确的类型的数量会爆炸,如果你开始跨越亚型和泛型类型层次的笛卡尔积,希望通过创建之类的东西更精确地专门IntegerArrayList
, IntegerAbstractList
, IntegerLinkedList
等。
使相关性通用
从上面可以看出,这种关联通常会从类型层次结构中删除通用性,尽管并不需要这样做。 在以下更一般的示例中可以看出:
// AnyContainer can contain AnyObject
class AnyContainer<E extends AnyObject> {}
class AnyObject {}// PhysicalContainer contains only PhysicalObjects
class PhysicalContainer<E extends PhysicalObject>extends AnyContainer<E> {}
class PhysicalObject extends AnyObject {}// FruitContainer contains only Fruit,
// which in turn are PhysicalObjects
class FruitContainer<E extends Fruit>extends PhysicalContainer<E> {}
class Fruit extends PhysicalObject {}
上面的示例是一个典型的示例,其中API设计者被诱使子类型多态性( Fruit extends PhysicalObject extends AnyObject
)与泛型多态性( <E>
)相关联,同时保持泛型,从而允许在FruitContainer
添加其他子类型。 AnyObject
当AnyObject
应该知道其自己的子类型时,这会变得更加有趣。 这可以通过递归泛型参数来实现。 让我们修复前面的示例
// AnyContainer can contain AnyObject
class AnyContainer<E extends AnyObject<E>> {}
class AnyObject<O extends AnyObject<O>> {}// PhysicalContainer contains only PhysicalObjects
class PhysicalContainer<E extends PhysicalObject<E>>extends AnyContainer<E> {}
class PhysicalObject<O extends PhysicalObject<O>>extends AnyObject<O> {}// FruitContainer contains only Fruit,
// which in turn are PhysicalObjects
class FruitContainer<E extends Fruit<E>>extends PhysicalContainer<E> {}
class Fruit<O extends Fruit<O>>extends PhysicalObject<O> {}
这里有趣的部分不再是容器,而是AnyObject
类型层次结构,该结构将子类型多态与自身类型上的通用多态相关联! 这也可以通过java.lang.Enum
完成:
public class Enum<E extends Enum<E>>
implements Comparable<E> {public final int compareTo(E other) { ... }public final Class<E> getDeclaringClass() { ... }
}enum MyEnum {}// Which is syntactic sugar for:
final class MyEnum extends Enum<MyEnum> {}
危险所在?
枚举和我们的自定义之间的细微差别AnyObject
层次是事实MyEnum
通过被终止的两个正交分型技术递归自相关final
! 另一方面,除非将AnyObject
子类型也AnyObject
为最终类型,否则不应将其删除。 一个例子:
// "Dangerous"
class Apple extends Fruit<Apple> {}// "Safe"
final class Apple extends Fruit<Apple> {}
为什么final
如此重要,或者换句话说,为什么在终止递归自相关(例如Apple
之前)时必须小心AnyObject
子类型? 这很简单。 让我们假设以下内容:
class AnyObject<O extends AnyObject<O>>implements Comparable<O> {@Overridepublic int compareTo(O other) { ... }public AnyContainer<O> container() { ... }
}
上述关于AnyObject.compareTo()
约定意味着, AnyObject
任何子类型都只能与同一子类型进行比较。 以下是不可能的:
Fruit<?> fruit = // ...
Vegetable<?> vegetable = // ...// Compilation error!
fruit.compareTo(vegetable);
层次结构中当前唯一可比较的类型是Apple:
Apple a1 = new Apple();
Apple a2 = new Apple();a1.compareTo(a2);
但是,如果我们想添加GoldenDelicious
和Gala
苹果怎么办?
class GoldenDelicious extends Apple {}
class Gala extends Apple {}
我们现在可以比较它们!
GoldenDelicious g1 = new GoldenDelicious();
Gala g2 = new Gala();g1.compareTo(g2);
这不是AnyObject
作者的AnyObject
!
这同样适用于container()
方法。 允许子类型协变地专门化AnyContainer
类型,这很好:
class Fruit<O extends Fruit<O>>extends PhysicalObject<O> {@Overridepublic FruitContainer<O> container() { ... }
}
但是, GoldenDelicious
和Gala
的container()
方法会GoldenDelicious
?
GoldenDelicious g = new GoldenDelicious();
FruitContainer<Apple> c = g.container();
是的,它将返回一个Apple
容器,而不是AnyObject
设计人员想要的GoldenDelicious
容器。
子类型多态和泛型多态跨越正交类型轴。 使它们相互关联可能是类型系统中的设计气味。 使它们在同一类型上关联是危险的,因为很难正确处理。 用户将尝试终止基本类型的子类型上的递归泛型类型定义。 终止的原因是具有递归自绑定的基本类型很难使用的事实。 但是终止通常会出错,因为它只能在final
类上执行,而不能在常规类或接口上执行。
换句话说,如果您认为需要基于通用基本类型的递归泛型类型定义,请仔细考虑,如果确实需要,并且您的类型用户可以在final
类中正确终止递归泛型类型定义。
翻译自: https://www.javacodegeeks.com/2013/07/the-dangers-of-correlating-subtype-polymorphism-with-generic-polymorphism.html
tcga癌症亚型获取