简体   繁体   中英

Almost identical methods in superclass and subclass are clashing. Why?

public class TestClass {

    private class Parent {

        public Object returnSomething() {
            return new Object();
        }

    }

    private class Child extends Parent {

        public String returnIt() {
            return (String) super.returnSomething();
        }
    }

    private class GrandChild extends Child {

        public StringBuilder returnIt() {
            return (StringBuilder) super.returnSomething();
        }
    }

}

My IDE complains about that the method in child clashing with the method in grandchild. The method definitions are different on the return type, so I don't see how they can be clashing.

Can someone help me to understand what Java is not allowing here?

In Java, method overriding is not possible with different return type unless it is covariant return types for overridden methods.

StringBuilder is not a sub class of String so compiler is not allowing to overide the method returnIt()

public final class StringBuilder extends AbstractStringBuilder
implements java.io.Serializable, Comparable<StringBuilder>, CharSequence

So, if you change return type of returnIt() in Child , it will work,

private class Child extends Parent {

        public CharSequence returnIt() {
            return (String) super.returnSomething();
        }
    }

Both methods have same name and input arguments, so the compiler qualifies them as same method, even though their return type differs. Overriding method and changing only the return type is not acceptable by the compiler.

In order to return different type, you can:

  • use new method name, like (returnItAsStringBuilder)
  • add additional argument to your method

  • use generic types:

Example:

private class Child<T> extends Parent {

    public T returnIt() {
        return (T) super.returnSomething();
    }
}

private class GrandChild extends Child<StringBuilder> {

}

But looking at this code, it will always fail. You will get ClassCastExcception, because in Parent class you are creating plain Object, which cannot be casted to anything else.

You should consider abstract parent class;

private abstract  class Parent <T>{
    public abstract T returnSomething();
}

private class GrandChild extends Parent<StringBuilder> {
    @Override
    public StringBuilder returnSomething() {
        return new StringBuilder();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM