如何强制泛型类型参数作为接口?

Phi*_*hke 44 java generics interface

有没有一种方法在java中指定,泛型类的类型参数必须是一个接口(而不仅仅是扩展它!)

我想做的是以下内容:

public class MyClass<X extends SomeInterface, Y extends SomeOtherClass & X>
Run Code Online (Sandbox Code Playgroud)

这意味着Y必须是SomeOtherClass的子类并实现X.编译器目前得到的是

X型不是界面; 它不能指定为有界参数

那么,我怎样才能告诉编译器X必须始终是一个接口?

编辑:
好的,我想我稍微简化了我的问题.让我们使用我的实际应用程序域来使其更清晰:

我有一个用于表示图表的API.一包含节点边缘对象.所有这三个类都实现了Shape接口.形状可以具有子形状,父形状并且属于图形.

问题是,我需要制作这个API的两个版本:一个只具有基本功能的开源和一个具有更多功能的扩展版本.但是,扩展API必须只提供返回扩展类型的方法(ExtendedDiagram,ExtendedNode,ExtendedEdge和(此处出现问题)ExtendedShape).
所以我有这样的事情:

/* BASIC CLASSES */
public interface Shape<X extends Shape<X,Y>, Y extends Diagram<X,Y>>{
    public List<X> getChildShapes();
    public X getParent();
    public Y getDiagram();
    ...
}

public class Diagram<X extends Shape<X,Y>, Y extends Diagram<X,Y>> implements Shape<X,Y>{...}
public class Edge<X extends Shape<X,Y>, Y extends Diagram<X,Y>> implements Shape<X,Y>{...}
...

/* EXTENDED CLASSES */
public interface ExtendedShape extends Shape<ExtendedShape,ExtendedDiagram> { ... }

public class ExtendedDiagram extends Diagram<ExtendedShape,ExtenedDiagram> implements ExtendedShape { ... }
public class ExtendedEdge extends Edge<ExtendedShape,ExtenedDiagram> implements ExtendedShape { ... }
...
Run Code Online (Sandbox Code Playgroud)

扩展API工作正常,基本API代码提供了一些警告,但使用基本API时会出现主要问题:

public class SomeImporter<X extends Shape<X,Y>, Y extends Diagram<X,Y>, E extends Edge<X,Y>>{
    private Y diagram;

    public void addNewEdge(E newEdge){
        diagram.addChildShape(newEdge);
    ...
Run Code Online (Sandbox Code Playgroud)

最后一行给了我以下警告:

方法中的方法addChildShape(X)不适用于参数(E)

所以现在,我只想指出E还需要实现X,一切都会好的 - 我希望;)

这一切都有意义吗?你们知道这样做的方法吗?或者是否有更好的方法来获得具有上述限制的扩展API?
感谢您坚持我,非常感谢任何帮助!

idi*_*kop 15

您可以使用:

class Foo<T extends Number & Comparable> {...}
Run Code Online (Sandbox Code Playgroud)

具有一个类型参数的类Foo,必须使用类型为Number并且实现Comparable的类型实例化T.Foo.

  • 不能说你错了,但它并没有解决我的问题.如果你再次查看问题陈述,那么你会看到我在第一行中只使用了该构造.似乎当前的Java标准不允许在'&'之后使用泛型类型参数,但这正是我所需要的. (2认同)

Mik*_*sen 6

在泛型上下文中,<Type extends IInterface>处理扩展和实现。这是一个例子:

public class GenericsTest<S extends Runnable> {
    public static void main(String[] args) {
        GenericsTest<GT> t = new GenericsTest<GT>();
        GenericsTest<GT2> t2 = new GenericsTest<GT>();
    }
}

class GT implements Runnable{
    public void run() {

    }
}

class GT2 {

}
Run Code Online (Sandbox Code Playgroud)

GenericsTest 将接受 GT,因为它实现了 Runnable。GT2 没有,因此在尝试编译第二个 GenericsTest 实例时会失败。

  • 感谢您的回答,但这不是我想要表达的重点。我想要的是一个泛型类型参数(在你的例子中是“S”),它必须是一个接口。因此,您的类“GT”和“GT2”都会编译失败。带有“interface Executable extends Runnable”的接口“Executable”将通过 (3认同)

Vin*_*ent 1

也许你可以稍微简化你的模型:太多的泛型很快就会在可读性方面变得非常痛苦,如果你定义一个公共 API,这将是一个很大的问题。通常,如果您无法再理解括号内应该包含的内容,那么您就超出了您的需求 - 并且您不能指望用户比您自己更好地理解它......

无论如何,为了使您的代码编译,您可以尝试在Shape类型中定义类似的内容:

public <S extends Shape<?,?>> void addChildShape(S shape);
Run Code Online (Sandbox Code Playgroud)

应该可以做到这一点。

华泰