【问题标题】:Generic Type extends Interface but gets an incompatible type error通用类型扩展了接口,但得到一个不兼容的类型错误
【发布时间】:2018-06-18 02:11:40
【问题描述】:

我是 Java 新手——来自 PHP Python 世界。我确信这是一个简单的问题,并且我缺少一些基本的东西,但是经过几个小时的搜索和修补,我无法弄清楚。

我有一个 Path 类,一个 In 和一个 Out

public class Path<In extends PointInterface, Out extends PointInterface> {
    private In in;
    private Out out;

    public Path(In in, Out out) {
        this.in = in;
        this.out = out;
    }

    public In getIn() {
        return in;
    }

    public Out getOut() {
        return out;
    }
}

我有很多PointInterface 的实现,现在,假设QueueEndpoint

我希望能够使用这两个 PointInterface 实现的任意组合来实例化 Path 对象。

这一切都很简单。 Path path = new Path&lt;&gt;(new Endpoint(), new Queue());

问题在于每个实现都有自己的 In 和 Out 处理程序。所以,在EndpointInHandler 里面,我可以确定path.getIn() 将返回一个Endpoint(它实现了PointInterface)。

但是,当我在该方法中尝试Endpoint in = path.getIn(); 时,我收到一个Incompatible Types 错误,指出它需要Endpoint,但找到了PointInterface

Endpoint 实现 PointInterface.

我试过了:

  • 在处理程序中定义泛型,如InHandlerInterface&lt;Endpoint&gt;
  • 不使用extends 逻辑,但是我对Object 有同样的问题
  • 使用抽象类而不是接口
  • 还有其他一些事情。

谁能帮我理解我错过了什么?非常感谢:)

代码示例

在我的 Main 方法中

Path path = new Path<>(new Endpoint(), new Queue());

InHandlerInterface handler = path.getIn().getInHandler(); // returns the EndpointInHandler
handler.handle(path);

Path详述如上。

PointInterface

public interface PointInterface {
    InHandlerInterface getInHandler();
}

Endpoint

public class Endpoint implements PointInterface {
    @Override
    public InHandlerInterface getInHandler() {
        return new EndpointInHandler();
    }

    public String specificToEndpoint() {
        return "Whatever";
    }
}

InHandlerInterface

public interface InHandlerInterface {
    void handle(Path path);
}

EndpointInHandler:

public class EndpointInHandler implements InHandlerInterface {
    @Override
    public void handle(Path path) {
        Endpoint in = path.getIn(); // This is giving me the Incompatible types error

        String whatever = in.specificToEndpoint();
    }
}

【问题讨论】:

  • 您的问题似乎有点令人困惑。你能放一个reproducible示例代码,并指出你在代码中的哪个地方得到了错误吗?这样您就可以更快地获得解决方案。
  • @Codebender 我可以尝试,但它有几个类。让我试着配对到熊市最低价。
  • @Codebender 有帮助吗?
  • 即使您将所有泛型传播到它们需要去的地方,在您调用path.getIn() 时,您所知道的只是getIn() 返回一些实现PointInterface 的未知类。不能保证它是Endpoint。泛型非常有用,但它们并不像来自另一种语言的人那样强大。它们实际上只是编译时的语法糖,用于强制类型安全并消除一些强制转换。泛型类型信息不会传播到运行时,因此您尝试完成的操作无法使用泛型完成。

标签: java generics inheritance interface polymorphism


【解决方案1】:

当您执行Path path = new Path&lt;&gt;(new Endpoint(), new Queue()) 时,您实际上已经失去了泛型的类型。

您需要将其写为Path&lt;EndPoint, Queue&gt; path = new Path&lt;&gt;(new Endpoint(), new Queue()),以便编译器知道泛型所指的实际类型。

更新

再看一遍,我意识到您需要将泛型放在任何地方。泛型无处不在可能看起来很奇怪,但这是确保编译时类型安全的方法。这样做,您将不需要任何显式强制转换。

Path<Endpoint, Queue> path = new Path<>(new Endpoint(), new Queue());

InHandlerInterface<Endpoint> handler = path.getIn().getInHandler(); // returns the EndpointInHandler
handler.handle(path);

点接口:

public interface PointInterface<T extends PointInterface> {
    InHandlerInterface<T> getInHandler();
}

端点:

public class Endpoint implements PointInterface<Endpoint> {
    @Override
    public InHandlerInterface<Endpoint> getInHandler() {
        return new EndpointInHandler<>();
    }

    public String specificToEndpoint() {
        return "Whatever";
    }
}

处理程序接口:

public interface InHandlerInterface<T extends PointInterface<T>> {
    void handle(Path<T, ?> path);
}

EndpointInHandler:

public class EndpointInHandler implements InHandlerInterface<Endpoint> {
    @Override
    public void handle(Path<Endpoint, ?> path) {
        Endpoint in = path.getIn(); // This is naturally type safe, and compiler won't complain

        String whatever = in.specificToEndpoint();
    }
}

【讨论】:

  • 谢谢!这两种解决方案都有效。对更新的一项更正:我必须将&lt;T extends PointInterface&gt; 添加到public class EndpointInHandler&lt;T extends PointInterface&gt;,即使从未使用过T。否则,它会抛出一个错误,即我在非泛型类型上使用了菱形运算符。
  • 你可能想把接口中的定义写成&lt;T extends PointInterface&lt;T&gt;&gt;(末尾的&lt;T&gt;已经加了)
  • @Lino 好点。这就是不使用IDE来回答的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-04
  • 2015-08-18
  • 1970-01-01
  • 2017-12-07
  • 1970-01-01
  • 2018-04-21
  • 2019-04-01
相关资源
最近更新 更多