我有这个设计,我不确定它为什么不起作用。
interface BaseType {}
interface TypeA extends BaseType {}
interface TypeB extends BaseType {}
interface Query<T extends BaseType> {
public String get();
}
interface Result<T extends BaseType> {
public String get();
}
interface Service<T extends BaseType> {
public Result<T> get(Query<T> query);
}
class SomeResult implements Result<TypeA> {
private String s;
public SomeResult(String s) { this.s = s; }
public String get() { return this.s; }
}
class SomeQuery implements Query<TypeA> {
public String get() { return "blah"; }
}
class SomeQuery2 implements Query<TypeA> {
public String get() { return "blah2"; }
}
class SomeService implements Service<TypeA> {
/** OK -- but notice the ambiguous parameter type */
/*
public SomeResult get(Query<TypeA> query) {
if (query instanceof SomeQuery) return new SomeResult(query.get());
else return null;
}
*/
/** NOT OK -- but this is the parameter I want to keep; notice SomeQuery IS-A Query<TypeA> */
public SomeResult get(SomeQuery query) { return new SomeResult(query.get()); };
/**
* Main.java:27: error: SomeService is not abstract and does not override abstract method get(Query<TypeA>) in Service
* class SomeService implements Service<TypeA> {
* ^
* 1 error
*/
}
public class Main {
public static void main(String args[]) {
SomeQuery someQuery = new SomeQuery();
SomeQuery2 someQuery2 = new SomeQuery2();
SomeService someService = new SomeService();
System.out.println(someService.get(someQuery).get());
}
}
我是仿制药的新手,并不太明白我在这里违反了什么合同。我希望服务紧密有限,即使我可以绑定返回类型,我似乎也不能这样做参数。这意味着,我需要在服务中进行instanceof
检查,以确保我获得正确的参数。我想避免这种情况。有什么想法吗?
答案 0 :(得分:1)
由于return type covariance,您可以使覆盖方法的返回类型更具体,但是您无法在不更改其签名的情况下更改方法的参数。这就是编译器抱怨您在将其更改为get(Query<TypeA>)
时未实现get(SomeQuery)
的原因。您需要使Service
更灵活,才能获得所需内容:
interface Service<T extends BaseType, Q extends Query<T>> {
public Result<T> get(Q query);
}
class SomeService implements Service<TypeA, SomeQuery> {
@Override
public SomeResult get(SomeQuery query) {
...
}
}
另请注意,编码到界面时缩小的返回类型无关紧要:当SomeService
键入为Service<TypeA, SomeQuery>
时,get
仍会返回Result<TypeA>
。因此,您可以考虑对结果类型进行类似的更改:
interface Service<T extends BaseType, Q extends Query<T>, R extends Result<T>> {
public R get(Q query);
}
class SomeService implements Service<TypeA, SomeQuery, SomeResult> {
@Override
public SomeResult get(SomeQuery query) {
...
}
}