0

我有几个 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()LoadDriverTargetgetTarget()LoadgetLoad()

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

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

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

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

4

2 回答 2

4

是的,你需要泛型:

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)方法。实际上,根据合同,目标应该接受任何类型的负载作为参数。并且HttpTarget'fire()方法只接受 HttpLoad 的实例,因此违反了 Liskov 原则。泛型是解决这个问题的方法。

于 2012-09-20T13:15:39.077 回答
0

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

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
于 2012-09-20T13:35:35.317 回答