【问题标题】:Inheritance and Multiple Collaborators继承和多个协作者
【发布时间】:2012-09-20 13:09:48
【问题描述】:

我有几个 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);

所以基本上Target 可以fire()Load。我的主应用程序Driver 不关心getTarget() 返回什么样的Target,或者getLoad() 返回什么样的Load。它的工作是确保负载被触发。

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

@Override
public void fire(HttpLoad httpLoad) {
    // ...
}

但是,当我这样做时,Java 抱怨方法覆盖与其父类 Target 提供的定义不匹配(因为 LoadHttpLoad 是两个不同的东西)。

这里有什么解决方案?泛型?抽象工厂? 最终,我希望能够强制HttpTargetfire() 方法只能接受HttpLoads,但仍与Driver 代码兼容。 有人可以提供代码吗例子?提前致谢!

【问题讨论】:

  • 您是否尝试删除 @Override 注释?

标签: java generics inheritance


【解决方案1】:

是的,你需要泛型:

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

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

【讨论】:

  • +1 不错!有没有办法只将方法声明为泛型并覆盖它以仅接受子类?
【解决方案2】:

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

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

    }

}

现在如果你写

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 2013-04-24
    • 2013-01-14
    • 2015-12-23
    • 2014-10-11
    • 1970-01-01
    相关资源
    最近更新 更多