【问题标题】:Java inherited return typeJava 继承的返回类型
【发布时间】:2012-10-26 09:37:02
【问题描述】:

我有一个关于 Java 中继承方法中的返回类型的问题。我有一个类和一个继承类。在继承的类中,有一个特定的方法。它还从返回自身实例的父类继承了一个方法。

我想要这样的类层次结构:

public class Foo {
    public Foo bar()
    {
        return this;
    }
}

public class FooInherited extends Foo {
    public Whatever baz()
    {
        return new Whatever();
    }
}

我的问题是我是否可以从它的实例调用继承的方法,然后调用特定的方法而不重写该方法以返回继承的类或显式转换类。

现在我想要一个这样的代码片段:

FooInherited foo = new FooInherited();
Whatever w = foo.bar().baz();

我觉得这有点困难,但我不太确定 Java 在这种情况下是否有任何为程序员节省时间的机制。

【问题讨论】:

    标签: java inheritance return-type


    【解决方案1】:

    您可以使用泛型,但它很快就会变得丑陋。

    class Base<This extends Base<This>> {
    
        public This myself() {
            return (This) this;
        }
    
    }
    
    class Sub<This extends Sub<This>> extends Base<This> {
    
        public void subOnly() {}
    
    }
    
    {
        Sub<?> sub = new Sub<>();
        sub.myself().subOnly();
        Base<?> base = sub;
        // base.myself().subOnly(); // compile error
    }
    

    另一种方法是显式覆盖该方法:

    class Base {
    
        public Base myself() {
            return this;
        }
    
    }
    
    class Sub extends Base {
    
        @Override
        public Sub myself() {
            return this; // or return (Sub) super.myself();
        }
    
        public void subOnly() {}
    
    }
    
    {
        Sub sub = new Sub();
        sub.myself().subOnly();
        Base base = sub;
        // base.myself().subOnly(); // compile error
    }
    

    【讨论】:

    • 谢谢你的回答,我想,那是不可能的。
    • 我必须实现 super 声明有点不同 Base &lt;This extends Base&lt;This&gt;&gt; 指出 here
    • 正确,我忘了添加内部通用参数
    • 如果链中的最后一个类将自身用作类型...使用该类时无需指定泛型类型:class SubSub extends Sub .... SubSub subSub = new SubSub (); subSub.myself().subOnly().subSubOnly();
    【解决方案2】:

    除非你重写子类中的方法,否则你将不得不强制转换:

    FooInherited foo = new FooInherited();
    Whatever w = ((FooInherited)foo.bar()).baz();
    

    但是,由于 java 中的covariant return types,您可以像这样覆盖它:

    public class FooInherited extends Foo {
    
    
            @Override
            public FooInherited bar()
            {
                return this;
            }
     ...
     }
    

    覆盖后您不再需要强制转换,因为 foo 的静态类型是 FooInherited

    FooInherited foo = new FooInherited();
    Whatever w = foo.bar().baz();
    

    【讨论】:

      【解决方案3】:

      foo.bar() 返回一个Foo 实例,它没有名为baz() 的方法, 所以无法编译这个语句:Whatever w = foo.bar().baz();

      【讨论】:

        猜你喜欢
        • 2017-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-21
        • 1970-01-01
        • 2012-04-05
        • 2012-10-18
        相关资源
        最近更新 更多