通用类型扩展了接口但得到了不兼容的类型错误

时间:2018-01-09 04:31:33

标签: java generics inheritance interface polymorphism

我是Java新手 - 来自PHP Python世界。我确信这是一个简单的问题,而且我遗漏了一些基本的东西,但经过几个小时的搜索和修补,我无法弄明白。

我有一个Path课程,可以保持积分,InOut

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

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

这一切都很简单。 Path path = new Path<>(new Endpoint(), new Queue());

问题每个实现都有自己的In和Out处理程序。因此,在EndpointInHandler内,我可以确定path.getIn()将返回Endpoint(实现PointInterface)。

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

Endpoint 实施 PointInterface

我试过了:

  • InHandlerInterface<Endpoint>
  • 等处理程序中定义泛型
  • 没有使用extends逻辑,但我遇到与Object相同的问题
  • 使用抽象类而不是接口
  • 以及其他一些事情。

任何人都可以帮助我理解我所缺少的东西吗?非常感谢:)

代码示例

在我的主要方法中

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();
    }
}

1 个答案:

答案 0 :(得分:2)

执行Path path = new Path<>(new Endpoint(), new Queue())时,您实际上已经失去了泛型的类型。

您需要将其编写为Path<EndPoint, Queue> path = new Path<>(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);

PointInterface:

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";
    }
}

InHandlerInterface:

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();
    }
}