Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java inherited return type

I've got a question about return types in inherited methods in Java. I've got a class and an inherited class. In the inherited class, there's a specific method. It also inherits a method from the parent class that returns instance of itself.

I want something like this class hierarchy:

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

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

My question is if I can call the inherited method from its instance and then call the specific method without overriding the method to return the inherited class or casting the classes explicitly.

Now I want to have a code fragment like this :

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

I feel a difficulty in this, but I'm not very sure if Java has any time saving mechanism for programmers in such situations.

like image 403
Danstahr Avatar asked Oct 26 '12 09:10

Danstahr


2 Answers

You can use generics, but it gets ugly quickly.

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
}

The alternative is to override the method explicitly:

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
}
like image 94
Cephalopod Avatar answered Sep 23 '22 21:09

Cephalopod


Unless you override the method in the subclass you will have to cast:

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

However, due to covariant return types in java you can override it like this:

public class FooInherited extends Foo {


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

After overriding you no longer have to cast because the static type of foo is FooInherited:

FooInherited foo = new FooInherited();
Whatever w = foo.bar().baz();
like image 24
cyon Avatar answered Sep 25 '22 21:09

cyon