122.md 3.9 KB
Newer Older
W
init  
wizardforcel 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
# 泛型,继承和子类型

> 原文: [https://docs.oracle.com/javase/tutorial/java/generics/inheritance.html](https://docs.oracle.com/javase/tutorial/java/generics/inheritance.html)

如您所知,只要类型兼容,就可以将一种类型的对象分配给另一种类型的对象。例如,您可以将`整数`分配给`对象`,因为`对象``整数`的超类型之一:

```
Object someObject = new Object();
Integer someInteger = new Integer(10);
someObject = someInteger;   // OK

```

在面向对象的术语中,这被称为“是一种”关系。由于`整数` _ 是 _ 种`对象`,因此允许分配。但是 `Integer` 也是一种 `Number` ,所以下面的代码也是有效的:

```
public void someMethod(Number n) { /* ... */ }

someMethod(new Integer(10));   // OK
someMethod(new Double(10.1));   // OK

```

仿制药也是如此。您可以执行泛型类型调用,将 `Number` 作为其类型参数传递,如果参数与 `Number` 兼容,则允许 `add` 的任何后续调用:

```
Box<Number> box = new Box<Number>();
box.add(new Integer(10));   // OK
box.add(new Double(10.1));  // OK

```

现在考虑以下方法:

```
public void boxTest(Box<Number> n) { /* ... */ }

```

它接受什么类型的论据?通过查看其签名,您可以看到它接受一个类型为 `Box&lt; Number&gt;的参数。` 。但是,这是什么意思?您是否可以通过 `Box&lt; Integer&gt;``Box&lt; Double&gt;` ,正如您所料?答案是“不”,因为 `Box&lt; Integer&gt;``Box&lt; Double&gt;` 不是 `Box&lt; Number&gt;的亚型。`

在使用泛型编程时,这是一个常见的误解,但这是一个需要学习的重要概念。

W
wizardforcel 已提交
44
![diagram showing that Box<Integer> is not a subtype of Box<Number>](img/4953ad914ddbdaec1fe145e50985a7d2.jpg)
W
init  
wizardforcel 已提交
45

W
wizardforcel 已提交
46
`Box<Integer>` is not a subtype of `Box<Number>` even though `Integer` is a subtype of `Number`.
W
init  
wizardforcel 已提交
47 48 49 50 51 52 53 54 55 56 57 58 59

* * *

**Note:** Given two concrete types `A` and `B` (for example, `Number` and `Integer`), `MyClass<A>` has no relationship to `MyClass<B>`, regardless of whether or not `A` and `B` are related. The common parent of `MyClass<A>` and `MyClass<B>` is `Object`.

For information on how to create a subtype-like relationship between two generic classes when the type parameters are related, see [Wildcards and Subtyping](subtyping.html).

* * *

您可以通过扩展或实现泛型类或接口来对其进行子类型化。一个类或接口的类型参数与另一个类型参数的类型参数之间的关系由 `extends``实现`子句确定。

使用`集合`类作为示例, `ArrayList&lt; E&gt;` 实现 `List&lt; E&gt;``列表&lt; E&gt; extends Collection&lt; E&gt;` 。所以 `ArrayList&lt; String&gt;``List&lt; String&gt;的子类型。` ,它是 `Collection&lt; String&gt;的子类型。` 。只要不改变类型参数,就会在类型之间保留子类型关系。

W
wizardforcel 已提交
60
![diagram showing a sample collections hierarchy: ArrayList<String> is a subtype of List<String>, which is a subtype of Collection<String>.](img/53a7bba39584accc105f76c8b7af56b3.jpg)
W
init  
wizardforcel 已提交
61

W
wizardforcel 已提交
62
A sample `Collections` hierarchy
W
init  
wizardforcel 已提交
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79

现在假设我们想要定义我们自己的列表接口, `PayloadList` ,它将泛型类型 `P` 的可选值与每个元素相关联。它的声明可能如下:

```
interface PayloadList<E,P> extends List<E> {
  void setPayload(int index, P val);
  ...
}

```

`PayloadList` 的以下参数化是 `List&lt; String&gt;的子类型。`

*   `PayloadList&lt; String,String&gt;`
*   `PayloadList&lt; String,Integer&gt;`
*   `PayloadList&lt; String,Exception&gt;`

W
wizardforcel 已提交
80
![diagram showing an example PayLoadList hierarchy: PayloadList<String, String> is a subtype of List<String>, which is a subtype of Collection<String>. At the same level of PayloadList<String,String> is PayloadList<String, Integer> and PayloadList<String, Exceptions>.](img/4ba0deb28efaf72ab893f651aff1a11b.jpg)
W
init  
wizardforcel 已提交
81

W
wizardforcel 已提交
82
A sample `PayloadList` hierarchy