Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java泛型-为什么是;扩展T";“允许但不允许”;实施T";?_Java_Generics_Syntax_Design Choices - Fatal编程技术网

Java泛型-为什么是;扩展T";“允许但不允许”;实施T";?

Java泛型-为什么是;扩展T";“允许但不允许”;实施T";?,java,generics,syntax,design-choices,Java,Generics,Syntax,Design Choices,我想知道在Java中总是使用“extends”而不是“implements”来定义typeparameters的边界是否有特殊的原因 例如: public interface C {} public class A<B implements C>{} 公共接口C{} 公共A类{} 禁止,但 public class A<B extends C>{} 公共类A{} 这是正确的。原因是什么?在泛型约束语言中,类是“实现”还是“扩展”在语义上没有区别。约束的可能性是

我想知道在Java中总是使用“
extends
”而不是“
implements
”来定义typeparameters的边界是否有特殊的原因

例如:

public interface C {}
public class A<B implements C>{} 
公共接口C{}
公共A类{}
禁止,但

public class A<B extends C>{} 
公共类A{}

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

在泛型约束语言中,类是“实现”还是“扩展”在语义上没有区别。约束的可能性是“extends”和“super”——也就是说,这个类是否可以分配给另一个类(extends),或者这个类是否可以从那个类(super)分配。可能是基类型是泛型参数,所以实际类型可能是类的接口。考虑:

class MyGen<T, U extends T> {
类MyGen{

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

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

public class A<B extends C>{}

我通常认为“Sub扩展Super”是“Sub类似于Super,但具有附加功能”,而“Clz实现Intf”是“Clz是Intf的实现”。在您的示例中,这将匹配:B类似于C,但具有附加功能。这些功能与此处相关,而不是实现。

这里是一个更复杂的示例,其中倾向是允许的,并且可能是您想要的:


公共类A

使用哪一个术语是任意的。可能是任意一种。也许语言设计者认为“扩展”是最基本的术语,“实现”是接口的特例

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

Java词汇表表达了一个问题。

答案如下:

要声明有界类型参数,请列出类型参数的名称,后跟
extends
关键字,后跟其上限[…]。请注意,在此上下文中,extends通常表示
extends
(在类中)或
implements
(在接口中)

所以你有了它,它有点让人困惑,Oracle知道这一点。

我们已经习惯了

class ClassTypeA implements InterfaceTypeA {}
class ClassTypeB extends ClassTypeA {}
任何对这些规则的轻微偏离都会让我们非常困惑

类型绑定的语法定义为

TypeBound:
    extends TypeVariable 
    extends ClassOrInterfaceType {AdditionalBound}
()

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

TypeBound:
    extends TypeVariable 
    extends ClassType {AdditionalBound}
    implements InterfaceType {AdditionalBound}
最后得到两个处理相同的子句

ClassOrInterfaceType:
    ClassType 
    InterfaceType
()

除此之外,我们还需要处理
实现
,这将使事情进一步复杂化

我相信这是使用
扩展类或接口类型
而不是
扩展类类型
实现接口类型
的主要原因,以便在复杂的概念中保持简单。问题是我们没有合适的词来涵盖
扩展
实现
,并且我们定义了它伊利不想介绍一个



虽然
扩展
在与接口一起使用时会带来一些混乱,但它是一个更广泛的术语,可以用来描述这两种情况。试着让你的头脑适应扩展类型的概念(不扩展类,不实现接口)。您可以通过另一个类型来限制类型参数,而这与该类型实际上是什么无关。重要的是它的上限,以及它的超类型

事实上,在接口上使用泛型时,关键字也是扩展。下面是代码示例:

有两个类实现了问候语接口:

interface Greeting {
    void sayHello();
}

class Dog implements Greeting {
    @Override
    public void sayHello() {
        System.out.println("Greeting from Dog: Hello ");
    }
}

class Cat implements Greeting {
    @Override
    public void sayHello() {
        System.out.println("Greeting from Cat: Hello ");
    }
}
以及测试代码:

@Test
public void testGeneric() {
    Collection<? extends Greeting> animals;

    List<Dog> dogs = Arrays.asList(new Dog(), new Dog(), new Dog());
    List<Cat> cats = Arrays.asList(new Cat(), new Cat(), new Cat());

    animals = dogs;
    for(Greeting g: animals) g.sayHello();

    animals = cats;
    for(Greeting g: animals) g.sayHello();
}
@测试
公共void testGeneric(){

CollectionConserve.E不能是类。@TomHawtin tackline除了不能使用类型参数(“E”)之外,您必须在该符号和字符后面加上一个接口文字,以便Java可以信任您它是一个接口。我希望在这一点上得到更正。@JaroslavZáruba这是真的。实际错误是“需要意外的类型:class found:type parameter E”(我强调的是“class”)。然而,最初的海报(不幸的是)使用了单个字母作为类型名称以及类型参数=
E
应该意味着写一个实际的类型名称(我想——我在十多年前写过这条评论).@TomHawtin tackline Dam,我希望能有一个解决办法:)@KomodoDave(我想答案旁边的数字会将其标记为正确,我不确定是否有其他标记方法,有时其他答案可能包含其他信息-例如,我有一个无法解决的特定问题,谷歌在搜索时会将您发送到这里。)@Tetsujin no Oni(是否可以使用一些代码来澄清?thanx:))@ntg,这是一个非常好的例子,关于一个寻找例子的问题,我将在注释中链接它,而不是在这一点上嵌入答案。我认为原因至少是我希望有一个泛型,它可以有一个构造函数和方法,可以接受任何一个类,既可以是基类,也可以展示一个接口,而不仅仅是interfa扩展接口的CE。然后实例化接口存在的Genric测试,并将实际类指定为类型参数。理想情况下,我希望
类Generic{Generic(RenderableT toDrag){x=(Draggable)toDrag;}
需要编译时检查。@peterk和RenderableT扩展了Renderable、Dragable、Dropable……除非我不明白您希望erasure泛型为您做什么
@Test
public void testGeneric() {
    Collection<? extends Greeting> animals;

    List<Dog> dogs = Arrays.asList(new Dog(), new Dog(), new Dog());
    List<Cat> cats = Arrays.asList(new Cat(), new Cat(), new Cat());

    animals = dogs;
    for(Greeting g: animals) g.sayHello();

    animals = cats;
    for(Greeting g: animals) g.sayHello();
}