Java 继承和多个协作者

Java 继承和多个协作者,java,generics,inheritance,Java,Generics,Inheritance,我有几个Java接口/ABC/类: public abstract class Target { public abstract void fire(Load load); } public class HttpTarget extends Target { @Override public void fire(Load load) { // ... } } public interface Load { // ... } publi

我有几个Java接口/ABC/类:

public abstract class Target {
    public abstract void fire(Load load);
}

public class HttpTarget extends Target {
    @Override
    public void fire(Load load) {
        // ...
    }
}

public interface Load {
    // ...
}

public class HttpLoad implements Load {
    // ...
}

// Inside a driver
Target target = testSuite.getTarget();
Load load = testSuite.getLoad();

target.fire(load);
因此本质上,一个
目标
可以
开火()
一个
装载
。我的主应用程序
Driver
不关心
getTarget()
返回什么类型的
Target
,或者
getLoad()
返回什么类型的
Load
。它的工作是确保一个负载被触发

我想将
HttpTarget
中的
fire()
方法定义更改为:

@Override
public void fire(HttpLoad httpLoad) {
    // ...
}
然而,当我这样做时,Java抱怨方法覆盖与其父类
Target
类提供的定义不匹配(因为
Load
HttpLoad
是两件不同的事情)


这里的解决方案是什么?仿制药?抽象工厂最终,我希望能够强制执行
HttpTarget
fire()
方法只能接受
HttpLoad
s,但仍然与
驱动程序
代码兼容。
有人能提供一个代码示例吗?提前谢谢

是的,您需要泛型:

public abstract class Target<L extends Load> {
    public abstract void fire(L load);
}

public class HttpTarget extends Target<HttpLoad> {
    @Override
    public void fire(HttpLoad load) {
        ...
    }
}

public interface TestSuite<L extends Load> { // or class
    L getLoad();
    Target<L> getTarget();
}

public class HttpTestSuite implements TestSuite<HttpLoad> {
    @Override
    public HttpLoad getLoad() {
        ...
    }

    @Override
    public Target<HttpLoad> getTarget() {
        return new HttpTarget();
    }
}
公共抽象类目标{
公共空间火灾(L荷载);
}
公共类HttpTarget扩展了目标{
@凌驾
公共空隙火灾(HttpLoad负荷){
...
}
}
公共接口测试套件{///或类
L getLoad();
Target getTarget();
}
公共类HttpTestSuite实现了TestSuite{
@凌驾
公共HttpLoad getLoad(){
...
}
@凌驾
公共目标getTarget(){
返回新的HttpTarget();
}
}

Java拒绝编译HttpTarget类的原因是它没有覆盖目标的
fire(Load)
方法。事实上,根据合同,目标应该接受任何类型的负载作为参数。而
HttpTarget
fire()
方法只接受HttpLoad的实例,因此违反了Liskov原则。泛型是这个问题的解决方案。

是的,您需要泛型:

public abstract class Target<L extends Load> {
    public abstract void fire(L load);
}

public class HttpTarget extends Target<HttpLoad> {
    @Override
    public void fire(HttpLoad load) {
        ...
    }
}

public interface TestSuite<L extends Load> { // or class
    L getLoad();
    Target<L> getTarget();
}

public class HttpTestSuite implements TestSuite<HttpLoad> {
    @Override
    public HttpLoad getLoad() {
        ...
    }

    @Override
    public Target<HttpLoad> getTarget() {
        return new HttpTarget();
    }
}
公共抽象类目标{
公共空间火灾(L荷载);
}
公共类HttpTarget扩展了目标{
@凌驾
公共空隙火灾(HttpLoad负荷){
...
}
}
公共接口测试套件{///或类
L getLoad();
Target getTarget();
}
公共类HttpTestSuite实现了TestSuite{
@凌驾
公共HttpLoad getLoad(){
...
}
@凌驾
公共目标getTarget(){
返回新的HttpTarget();
}
}

Java拒绝编译HttpTarget类的原因是它没有覆盖目标的
fire(Load)
方法。事实上,根据合同,目标应该接受任何类型的负载作为参数。而
HttpTarget
fire()
方法只接受HttpLoad的实例,因此违反了Liskov原则。泛型是这个问题的解决方案。

你将不得不使用泛型,即使这样,它也不是你想要的

public interface Load<T extends Load> {

    public void someMethod();

}

public class HttpLoad implements Load<HttpLoad> {

    @Override
    public void someMethod() {
        System.out.println("Http Load");
                ...
    }

}

public abstract class Target<T extends Load> {

    public abstract void fire(Load<T> load);


}

public class HttpTarget extends Target<HttpLoad> {

    @Override
    public void fire(Load<HttpLoad> load) {
        load.someMethod();

    }

}
公共接口加载{
公共方法();
}
公共类HttpLoad实现加载{
@凌驾
公共方法(){
System.out.println(“Http加载”);
...
}
}
公共抽象类目标{
公共空间火灾(荷载);
}
公共类HttpTarget扩展了目标{
@凌驾
公共空间火灾(荷载){
load.someMethod();
}
}
现在如果你写信

Target<HttpLoad> httpTarget = new HttpTarget();
Load<HttpLoad> httpLoad = new HttpLoad();
Load<OtherLoad> otherLoad = new OtherLoad();
Load otherLoad2 = new OtherLoad();

httpTarget.fire(httpLoad);
httpTarget.fire(otherLoad); // this doesn't compile
httpTarget.fire(otherLoad2) // this how ever compiles
Target-httpTarget=new-httpTarget();
Load httpLoad=新httpLoad();
加载其他加载=新的其他加载();
Load otherLoad2=新的OtherLoad();
httpTarget.fire(httpLoad);
httpTarget.fire(其他负载);//这是不可编译的
httpTarget.fire(otherLoad2)//这是如何编译的

您将不得不使用泛型,即使这样,它也不是您想要的

public interface Load<T extends Load> {

    public void someMethod();

}

public class HttpLoad implements Load<HttpLoad> {

    @Override
    public void someMethod() {
        System.out.println("Http Load");
                ...
    }

}

public abstract class Target<T extends Load> {

    public abstract void fire(Load<T> load);


}

public class HttpTarget extends Target<HttpLoad> {

    @Override
    public void fire(Load<HttpLoad> load) {
        load.someMethod();

    }

}
公共接口加载{
公共方法();
}
公共类HttpLoad实现加载{
@凌驾
公共方法(){
System.out.println(“Http加载”);
...
}
}
公共抽象类目标{
公共空间火灾(荷载);
}
公共类HttpTarget扩展了目标{
@凌驾
公共空间火灾(荷载){
load.someMethod();
}
}
现在如果你写信

Target<HttpLoad> httpTarget = new HttpTarget();
Load<HttpLoad> httpLoad = new HttpLoad();
Load<OtherLoad> otherLoad = new OtherLoad();
Load otherLoad2 = new OtherLoad();

httpTarget.fire(httpLoad);
httpTarget.fire(otherLoad); // this doesn't compile
httpTarget.fire(otherLoad2) // this how ever compiles
Target-httpTarget=new-httpTarget();
Load httpLoad=新httpLoad();
加载其他加载=新的其他加载();
Load otherLoad2=新的OtherLoad();
httpTarget.fire(httpLoad);
httpTarget.fire(其他负载);//这是不可编译的
httpTarget.fire(otherLoad2)//这是如何编译的

您是否尝试删除@Override注释?是否尝试删除@Override注释?+1很好!有没有办法只将方法声明为泛型并重写它以只接受子类?+1很好!有没有办法只将方法声明为泛型并重写它以只接受子类?