4

可以在 Java 中的覆盖方法中缩小返回类型。

但是否有可能在声明期间强制缩小范围?

例如,这在模式中可能很好,其中内部类与外部类同时子类化:

public class Try_ForceNarrow {

    public interface IMember {

    }

    public interface Container<M extends IMember> {
        M createMember();
    }

    public static class A implements Container<A.Member> {

        @Override
        public Member createMember() {
            return new Member();
        }

        public class Member implements IMember {
        }
    }

    public static class B extends A implements Container<B.Member> {

        @Override
        public Member createMember() {
            return new Member();
        }

        public class Member extends A.Member {

        }

    }

    public static void main(String[] args) {

    }

}

此代码编译失败,并出现“接口容器不能使用不同的参数多次实现”的错误。

如何避免这种情况?

当然,我可以写

public static class B extends A  {

        @Override
        public Member createMember() {
            return new Member();
        }

        public class Member extends A.Member {

        }

    }

但是这样我就可以忘记覆盖createMember()和违反模式。

4

4 回答 4

0

我相信这可以满足您的要求。

您可以创建一个新的抽象类,Container它允许您不断扩展或缩小泛型,但您需要将每个类声明为静态:

class Try_ForceNarrow {

    public interface IMember {

    }

    public interface Container<M extends IMember> {
        M createMember();
    }

    //The abstract class that lets you continually extend or "narrow"
    public static abstract class A<E extends A.Member> implements Container<E> {

        public static class Member implements IMember {
        }
    }

    //Here is the first class that extends the Abstract Class A
    public static class B extends A<B.Member> { //This class now Implements Container<B.Member>

        @Override
        public Member createMember() {
            return new Member();
        }

        //Since this is the first extension we will extend A.Member
        public static class Member extends A.Member {

        }

    }

    //This is an additional class that extends A but we want to extend the functionality of B.Member also.
    public static class C extends A<C.Member> { //This class now Implements Container<C.Member>


        @Override
        public Member createMember() {
            return new Member();
        }

        //C.Member properly extends B.Member
        //if this class is going to be extended this needs to be static
        public class Member extends B.Member {

        }

    }
}

当然,如果您删除,则根据您的要求

@Override
public Member createMember() {
    return new Member();
}

从扩展的子类中,您会收到编译错误。

于 2015-01-16T19:22:54.613 回答
0

那么A<T> implements Container<T>呢?您可以根据需要进一步限制 T ...

于 2015-01-16T17:48:47.367 回答
0

在我看来,您希望每个子类C都有一个createMember工厂方法,该方法返回一个具有相同类型的新对象。问题是,如果C1提供了一个返回的工厂方法,C1然后C2扩展C1,就没有办法强制C2提供它自己的方法——它只能从C1.

我不认为有一个解决方案可以在编译时捕获错误,但也许你可以做一些在运行时捕获错误的事情:

abstract class MemberBase {

    protected abstract MemberBase doCreateMember();
    protected abstract Class<?> memberClass();

    public MemberBase createMember() {
         MemberBase result = doCreateMember();
         if (result.getClass() != memberClass()) {
             throw new RuntimeException("createMember returned the wrong class");
         }
         return result;
    }

}
public static class A extends MemberBase {

    @Override
    protected Member doCreateMember() {
        return new Member();
    }

    @Override
    protected Class<?> memberClass() {
        return Member.class;
    }

    public class Member implements IMember {
    }
}
public static class B extends A {

    // If you forget to define this, the doCreateMember in A will be
    // inherited, but it will return the wrong class and lead to a
    // run-time exception
    @Override
    protected Member doCreateMember() {
        return new Member();
    }

    @Override
    protected Class<?> memberClass() {
        return Member.class;
    }

    public class Member extends A.Member {
    }
}

我没有对此进行测试,我不确定它是否能满足您的要求。另外,我可能有一些语法错误。但也许这个,或者它的修改,可能是有用的。

于 2015-01-16T18:14:55.727 回答
-1

当然会失败,你的类Aimplements Container<A.Member>,但是你的类Bextends Abut also implements Container<B.Member>which like ,而且就编译器而言,和由于类型擦除class B extends A implements Container<A.Member> Container<B.Memeber>没有区别,编译后所有泛型信息都会丢失,所以类型擦除后没有 <……> ,只有它们的上限和下限存在,您的类型参数是无界的,因此它们将擦除为相同的类型,擦除后,您的类字面上看起来像这样,这根本是错误的。您可以缩小覆盖上的返回类型,这称为协变返回类型,这还将在 VM 中创建一个以保留泛型中的多态性。Container<A.Member>Container<B.Member>Bclass B extends A implements Container Containerbridge method

于 2015-01-16T18:02:10.140 回答