Home > Software design >  Is there a way to return current class type in a final method?
Is there a way to return current class type in a final method?

Time:03-26

I have the following situation in java; There is a class that implements a method that is meant to be final but I need the returning type of such method to be exactly that of the class that it calling it. Since I want the method to be final I can't modify the return data type in the subclasses since that would be illegal.

Is there a way to archive this without sacrificing finality and having to override such method for all subclasses that implement it?. Even if the method was not final it would still be faster to implement it this way.

The code would be something like this:

class Parent
{
    public currentClass finalMethod() {...}
}

class Children extends Parent {}

public static void main(String args[])
{
    Children c = new Children();
    System.out.print(c.finalMethod().getClass().getName()); // Would print Children
}

Tried to use reflection and generics to no avail. Examples:

class Parent
{
    public this.getClass() finalMethod() {...} //Many Errors
    public <extends Parent> finalMethod() {...} // Returns Parent even if called by Child
    public Class<? extends Parent>[] getVecinos() // Returns Class<? extends Parent> thus can't use polymorphism which is the use case
}

I know I could use casting but still not the best solution.

CodePudding user response:

The default behavior is that you'll get what you're looking for, as long as finalMethod does not generate new instances using other types.

To use your code:

class Parent {
    public final Parent finalMethod() {
        return this;
    }
}

With that, c.finalMethod().getClass().getName() returns Children. That's because this inside finalMethod() is the same object that was created using new Children() and getClass() returns the runtime class of the object.

That uses inheritance and as long as you can work with Parent as the return type, you should be fine. If, however, your objective is to call methods specific to Children on the return value of finalMethod(), you may need to make Parent generic. Something like this:

class Parent<C extends Parent<C>> {
    public final Parent<C> finalMethod() {
        //whatever
        return this;
    }
}
class Children extends Parent<Children> {
}

And that would make the following code valid, still producing the same output:

Parent<Children> c = new Children(); //or Children c = new Children();
System.out.print(c.finalMethod().getClass().getName());

This has the advantage of allowing you to make static reference to Child-specific methods without prior casting. But it's not the right solution unless it's okay to make Parent generic. It's also not fail-safe.

  • Related