3
votes

Suppose I have an inheritance chain where every class extends its superclass by adding a new field and I want every class of that chain to override the toString() method like so:

public String toString()
{
    return super.toString() + "[newfield=" + newfield + "]";
}

If I use an abstract base class then when a class of the inheritance chain becomes concrete by implementing the abstract method all the subclasses from that point on become concrete as well by inheriting the already implemented method.

Is there a way in Java to force every class to override (reimplement) the abstract method even though it has already been implemented higher in the inheritance chain?

2

2 Answers

3
votes

Short answer: no.

Long answer: you could write a unit test that scans the class path (use a library like reflections for that), loads every subclass of the abstract class and checks for the method using reflection. But there's no way to do it at compile time.

Aside from Java, AspectJ has a hasMethod() pointcut, which could do the check for you, but unfortunately that's only valid for the declare parents advice. Perhaps you could do it in two steps using aspectj:

  • define an interface IllBehaved.
  • define an advice that assigns this interface to classes that extend from your base class but don't have the member
  • then declare a compile error for all types that implement this interface

    pointcut isSubTypeOfYourClass(): within(com.your.BaseClass+);
    pointcut overridesMethod(): hasmethod(public void yourMethodName(..));
    declare parents: isSubTypeOfYourClass() && !overridesMethod()
                     implements com.yourcompany.IllBehaved;
    declare error: isSubTypeOfYourClass() && within(com.yourcompany.IllBehaved+):
                     "Implementation class must override <Foo> method";
    

I haven't tested this, but it should work if you turn on the -XhasMember option. And it's easy enough to integrate aspectj into your build when you use standard tools like Maven, Ant, Eclipse etc.

2
votes

No, but you could let your classes implement an interface instead of the abstract super class. You might can check on compile time if the class implements the interface, that depends on what you are doing with this classes.