我有这个设计,我不确定为什么它不起作用。

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检查,以确保获得正确的参数。我想避免这种情况。有任何想法吗?

最佳答案

由于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) {
        ...
    }
}

关于java - 泛型有界类型参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17731910/

10-11 22:34
查看更多