如何在重写方法中使用`Derived`类型的参数接受`Base`?

时间:2017-09-08 14:45:55

标签: java generics interface override

我有以下情况:

abstract class Base {
    int data = 0;
    void baseMethod() {
        System.out.println("baseMethod:" + data);
    }
}

class DerivedA extends Base {
    void DerivedBMethodA() {

    }

    void usefulMethod(Something something) {
        something.doSomething(this);
    }

    interface Something {
        void doSomething(DerivedA deriv);
    }
}

class DerivedB extends Base {
    void DerivedMethodB() {

    }
}

public class Temp {

    public static void main() {
        DerivedA a = new DerivedA();
        a.usefulMethod(new DerivedA.Something() {
            @Override
            public void doSomething(DerivedA deriv) {
                deriv.DerivedBMethodA();
            }
        });
    }

}

我想将usefulMethodSomething推送到Base类,以便DerivedB可以利用它。我希望Something.doSomething的实现能够使用派生类型,以便它可以访问派生的功能。

我该怎么做?

尝试

我尝试了以下内容:

abstract class Base {
    int data = 0;
    void baseMethod() {
        System.out.println("baseMethod:" + data);
    }


    void usefulMethod(Something something) {
        something.doSomething(this);
    }

    interface Something {
        void doSomething(Base deriv);
    }
}

class DerivedA extends Base {
    void DerivedBMethodA() {

    }
}

class DerivedB extends Base {
    void DerivedMethodB() {

    }
}

public class Temp {

    public static void main() {
        DerivedA a = new DerivedA();
        a.usefulMethod(new Base.Something() {
            @Override
            public void doSomething(DerivedA deriv) {
                deriv.DerivedBMethodA();
            }
        });
    }
}

但由于我的匿名Something没有实施doSomething(Base),因此失败了。所以试图使用泛型:

我试过了:

    interface Something {
        void doSomething(<? extends Base> deriv);
    }

但由于以下原因无法编译:“通配符只能用作参考参数”

我试过了:

    interface Something {
        <T extends Base> void doSomething(T deriv);
    }

但这需要我实现接口:

        a.usefulMethod(new Base.Something() {
            @Override
            public <T extends Base> void doSomething(T deriv) {

            }
        });

这显然不允许我访问派生类型?

有些方法可以使它“有效”,但它们是不受欢迎的:

  1. 此:

    interface Something {
        void doSomething(Base deriv);
    }
    
        a.usefulMethod(new Base.Something() {
            @Override
            public void doSomething(Base deriv) {
                DerivedA a1 = (DerivedA) deriv;
                a1.DerivedBMethodA();
            }
        });
    

    但这需要我在每个实施中投下,这似乎很浪费。

  2. 而且:

    package com.miurasample.ui.info;
    
    
    abstract class Base {
        int data = 0;
        void baseMethod() {
            System.out.println("baseMethod:" + data);
        }
    
    
        void usefulMethod(Something something) {
            something.doSomething(this);
        }
    
        interface Something<T extends Base> {
            void doSomething(T deriv);
        }
    }
    
    public class Temp {
    
        public static void main() {
            DerivedA a = new DerivedA();
            a.usefulMethod(new Base.Something<DerivedA>() {
                @Override
                public void doSomething(DerivedA deriv) {
    
                }
            });
        }
    }
    
  3. 但是会导致usefulMethod中的警告/ IDE突出显示:

    “未选中调用doSomething(T)作为原始类型Base.Something的成员”

    最简洁,最“干净”的方法是什么?那我是在理智吗?

1 个答案:

答案 0 :(得分:1)

很难说你的设计是否错误。我们没有足够的要求来断言,但这里是你想要做的干净的非铸造方法。它确实需要派生类中的额外方法:

public static void main(String... args) {
        DerivedA a = new DerivedA();

        a.usefulMethod( new Base.Something<DerivedA>() {
            @Override
            public void doSomething(DerivedA deriv) {
                deriv.DerivedBMethodA();
            }
        } );
    }

    public abstract static class Base< T extends Base<T> > {
        int data = 0;

        protected abstract T getThis();

        void baseMethod() {
            System.out.println("baseMethod:" + data);
        }

        void usefulMethod(Something<T> something) {
            something.doSomething( getThis() );
        }

        interface Something< T extends Base<T> > {
            void doSomething(T deriv);
        }
    }

    public static class DerivedA extends Base<DerivedA> {

        protected DerivedA getThis(){
            return this;
        }

        void DerivedBMethodA() {}
    }

    public static class DerivedB extends Base<DerivedB> {

        protected DerivedB getThis(){
            return this;
        }

        void DerivedMethodB() {}
    }