Java泛型 - 为什么允许"扩展T"而不是"实现T"?

use*_*623 293 java generics syntax design-choices

我想知道Java中是否存在使用always" extends"而不是" implements"来定义类型参数边界的特殊原因.

例:

public interface C {}
public class A<B implements C>{} 
Run Code Online (Sandbox Code Playgroud)

被禁止但是

public class A<B extends C>{} 
Run Code Online (Sandbox Code Playgroud)

是正确的.这是什么原因?

Tet*_*Oni 323

在类'实现'或'扩展'之间的通用约束语言中没有语义差异.约束的可能性是"扩展"和"超级" - 也就是说,这个类是否可以分配给另一个(扩展),或者这个类可以从那个(超级)分配.


Mik*_*elF 67

答案就在这里  :

要声明有界类型参数,请列出类型参数的名称,后跟extends关键字,后跟其上限 [...].请注意,在此上下文中,extends在一般意义上用于表示extends(如在类中)或implements(在接口中).

所以,你有它,它有点令人困惑,Oracle知道它.

  • 为了增加混乱,`getFoo(List&lt;? super Foo&gt; fooList)` 只适用于字面上由 Foo 扩展的类,如 `class Foo extends WildcardClass`。在这种情况下,`List&lt;WildcardClass&gt;` 将是可接受的输入。然而,任何`Foo` 实现的类都不起作用`class Foo 实现了NonWorkingWildcardClass` 并不意味着`List&lt;NonWorkingWildcardClass&gt;` 将在`getFoo(List&lt;? super Foo&gt; fooList)` 中有效。晶莹剔透! (2认同)

bee*_*tra 17

可能是因为对于双方(B和C),只有类型是相关的,而不是实现.在你的例子中

public class A<B extends C>{}
Run Code Online (Sandbox Code Playgroud)

B也可以是界面."extends"用于定义子接口和子类.

interface IntfSub extends IntfSuper {}
class ClzSub extends ClzSuper {}
Run Code Online (Sandbox Code Playgroud)

我通常认为'Sub extends Super'是' Sub就像Super,但有额外的功能','Clz实现Intf'为' ClzIntf的实现'.在您的示例中,这将匹配:B类似于C,但具有其他功能.这些功能与此相关,而不是实现.

  • 考虑<B扩展D&E>.E <caps>不得</ caps>成为一个班级. (10认同)

Tom*_*ine 7

可能是基类型是通用参数,因此实际类型可以是类的接口.考虑:

class MyGen<T, U extends T> {
Run Code Online (Sandbox Code Playgroud)

此外,从客户端代码角度来看,接口几乎与类无法区分,而对于子类型,它很重要.


ntg*_*ntg 7

这是一个更为复杂的例子,其中允许扩展,也可能是你想要的:

public class A<T1 extends Comparable<T1>>


And*_*lko 7

我们习惯了

class ClassTypeA implements InterfaceTypeA {}
class ClassTypeB extends ClassTypeA {}
Run Code Online (Sandbox Code Playgroud)

任何对这些规则的轻微偏离都会让我们感到非常困惑。

类型绑定的语法定义为

TypeBound:
    extends TypeVariable 
    extends ClassOrInterfaceType {AdditionalBound}
Run Code Online (Sandbox Code Playgroud)

( JLS 12 > 4.4. 类型变量 >TypeBound )

如果我们要改变它,我们肯定会添加这个implements案例

TypeBound:
    extends TypeVariable 
    extends ClassType {AdditionalBound}
    implements InterfaceType {AdditionalBound}
Run Code Online (Sandbox Code Playgroud)

并最终得到两个相同处理的子句

ClassOrInterfaceType:
    ClassType 
    InterfaceType
Run Code Online (Sandbox Code Playgroud)

( JLS 12 > 4.3. 引用类型和值 >ClassOrInterfaceType )

但我们还需要处理implements,这会使事情变得更加复杂。

extends ClassOrInterfaceType我相信这是使用 代替extends ClassTypeand的主要原因implements InterfaceType- 为了在复杂的概念中保持简单。问题是我们没有合适的词来涵盖这两者extendsimplements而且我们绝对不想引入一个词。

<T is ClassTypeA>
<T is InterfaceTypeA>

虽然extends它与接口一起使用时会带来一些混乱,但它是一个更广泛的术语,可以用来描述这两种情况。尝试将你的思想调整到扩展类型的概念(不是扩展类,不是实现接口)。您可以通过另一种类型来限制类型参数,并且该类型实际上是什么并不重要。唯一重要的是它是它的上限和它的超类型


Lii*_*Lii 5

这是任意使用哪个术语.它可能是两种方式.也许语言设计者认为"扩展"是最基本的术语,并且"实现"作为接口的特殊情况.

但我认为implements会更有意义.我认为更多地传达参数类型不必处于继承关系中,它们可以处于任何类型的子类型关系中.

Java Glossary表达了类似的观点.