Home > front end >  Overriding generic methods from base class
Overriding generic methods from base class

Time:09-17

I have a class heirarchies defined as follows:

class ClassA{}

class ClassB extends ClassA{}

class BaseClass
{
    public <T extends ClassA> T method1(){ return null; }

    public <T extends ClassA> T method2(T param1){ return null; }
}

I want to extend the above BaseClass and override the implementations of method1 and method2, but I'm struggling with the method signature in the DerivedClass. Here's what I tried:

class DerivedClass extends BaseClass
{
    @Override
    public ClassB method1() {return new ClassB();}

    @Override
    public ClassB method2(ClassB param1) {return new ClassB();}
}

For method1, I get the warning:

Type safety: The return type ClassB for method1() from the type DerivedClass needs unchecked conversion to conform to T from the type BaseClass

For method2, I get the following error:

The method method2(ClassB) of type DerivedClass must override or implement a supertype method

How do I resolve this?

Edit: I had to refactor the design and put the generic type on the BaseClass instead of each individual methods, so that such scenario doesn't occur.

CodePudding user response:

This method will works.

public class BaseClass<T extends ClassA> {
    public T method1() {
        return null;
    }

    public T method2(T param1) {
        return null;
    }
}
public class DerivedClass extends BaseClass<ClassB> {
    @Override
    public ClassB method1() {
        return new ClassB();
    }

    @Override
    public ClassB method2(ClassB param1) {
        return new ClassB();
    }
}

CodePudding user response:

The first warning is because JVM, due to type erasure cannot know whether the ClassB is proper (does it extend ClassA) and because there is a risk that some exception will be throw it warns you. To fix this you can add SuppressWarnings annotation over the method

@Override
@SuppressWarnings("unchecked")
public ClassB method1() {return new ClassB();}

The second thing is quite similar but now JVM cannot create proper type/method signature (please notice that return type is not included into signature in Java! Please also notice that public ClassA method2(ClassA param1) method would not cause such error).

To solve this you need to make compiler sure that the overridden method will have proper signature and to do this you need to move the generic type declaration on the class level

class BaseClass <T extends ClassA> 

then extend this class with proper type

class DerivedClass extends BaseClass<ClassB> {
    @Override
    public ClassB method1() { // notice that you don't need Suppress annotation anymore
        return new ClassB();
    }

    @Override
    public ClassB method2(ClassB param1) {
        return new ClassB();
    }
}

Now the compiler is able to check whether used type is in bound or not

class ClassC {}
class DerivedClass extends BaseClass<ClassC> {
// ERROR: Type parameter 'com.mantkowicz.example.ClassC' is not within its bound

Read more here:

  • Related