58

Is there any way of forcing child classes to override a non-abstract method of super class?

I need to be able to create instances of parent class, but if a class extends this class, it must give its own definition of some methods.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • I noticed there was a down-vote. I Never mind, but please also explain the reason of down-vote. –  Oct 20 '11 at 11:24
  • 3
    If a method is non-abstract it has a provided implementation. If it had a provided implementation but was "abstract" the provided implementation would be useless, as it would be discarded by the override. So why would you want this? – Raedwald Oct 20 '11 at 11:52
  • @Raedwald I mentioned in the question, that I need to be able to create instances of parent class also. Like Parent p=new Parent(); But if a method in Parent class is abstract, then I cannot do so.... That's the whole point. –  Oct 20 '11 at 12:44
  • Still, without seeing an example I am not buying the "subclasses must override this" part. What if you want to subclass Parent to change something that is unrelated to this method? – hugomg Oct 20 '11 at 13:39
  • 1
    This seems like maintenance woe waiting to happen. In cases where children must provide a different implementation of the method from the base class, defining an interface and having the abstract base class throw an exception is appropriate. If you expect your concrete class to be subclassed, your design is probably suboptimal. See the Open Closed Principle. – Visionary Software Solutions Oct 20 '11 at 18:08
  • @VisionarySoftwareSolutions You are right about 'maintenance' thing. But still there might be a scenario in which you are going to need this thing. –  Oct 20 '11 at 19:29
  • Speaking in hypotheticals makes anything possible. Given a concrete scenario, there is probably a more elegant/better way of doing it that doesn't involve this. – Visionary Software Solutions Oct 21 '11 at 00:12
  • 1
    You can set the superclass' method to throw a RuntimeException, then you at least know that you had to override it when testing. – Rob Fox Oct 25 '11 at 12:17
  • @VisionarySoftwareSolutions how does this disobey the Open/Closed principle? I don't see anyway this does so, since the clients of Parent class will be able to keep using Parent class. Newly added classes won't change the source or binaries of the Parent class. I don't know what you were talking about. – Aqeel Ashiq Nov 23 '15 at 06:22
  • @VisionarySoftwareSolutions seems like you don't have an answer. And used the term Open Closed Principle just in the excitement of knowing one more term. lol – Aqeel Ashiq Dec 09 '15 at 08:07
  • Using inheritance creates a situation where you're enforcing a tight coupling between two objects. This is often called the "fragile base class problem." You're likely to have to change the base class if a subclass would be broken by a bad assumption by the base. Josh Bloch talks about this in his Good API design talk and how Java did it wrong. https://www.youtube.com/watch?v=aAb7hSCtvGw#t=2600 – Visionary Software Solutions Jan 12 '16 at 01:31
  • @VisionarySoftwareSolutions That is a general problem with badly designed inheritance relationships and not specifically with the thing being asked in the OP – Aqeel Ashiq Jun 06 '22 at 05:44

13 Answers13

37

There is no direct compiler-enforced way to do this, as far as I know.

You could work around it by not making the parent class instantiable, but instead providing a factory method that creates an instance of some (possible private) subclass that has the default implementation:

public abstract class Base {
  public static Base create() {
    return new DefaultBase();
  }

  public abstract void frobnicate();

  static class DefaultBase extends Base {
    public void frobnicate() {
      // default frobnication implementation
    }
  }
}

You can't write new Base() now, but you can do Base.create() to get the default implementation.

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 9
    I feel the need to point out that a child class will not be able to get the parent's default implementation by calling `super.frobincate()` because a child class will be inheriting `Base` and not `DefaultBase`. Otherwise, this is a great work-around I think. – Anthony Oct 20 '11 at 12:14
24

As others have pointed out, you can't do this directly.

But one way to do this is to use the Strategy pattern, like so:

public class Base {
    private final Strategy impl;

    // Public factory method uses DefaultStrategy
    // You could also use a public constructor here, but then subclasses would
    // be able to use that public constructor instead of the protected one
    public static Base newInstance() {
        return new Base(new DefaultStrategy());
    }

    // Subclasses must provide a Strategy implementation
    protected Base(Strategy impl) {
        this.impl = impl;
    }

    // Method is final: subclasses can "override" by providing a different
    // implementation of the Strategy interface
    public final void foo() {
        impl.foo();
    }

    // A subclass must provide an object that implements this interface
    public interface Strategy {
        void foo();
    }

    // This implementation is private, so subclasses cannot access it
    // It could also be made protected if you prefer
    private static DefaultStrategy implements Strategy {
        @Override
        public void foo() {
            // Default foo() implementation goes here
        }
    }
}
Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135
6

Consider making an interface with this method. Class descendants will have to implement it.

Ivan Nikitin
  • 3,578
  • 27
  • 39
  • 1
    How would that help? If the base class needs to be instantiable, then it too would need to implement it. This would negate the need of the derived classes to implement them methods. – Joachim Sauer Oct 20 '11 at 07:33
  • 2
    There is no need to implement it by the base class. Ask for an interface instance where you need to use the derived object, not a base class instance. This will force derived classes to have an interface implementation. You may check for a base class type in the method body also. – Ivan Nikitin Oct 20 '11 at 12:26
5

I think the easiest way is to create an abstract class that inherits from the base class:


public class Base {
    public void foo() {
        // original method
    }
}

abstract class BaseToInheritFrom extends Base {
    @Override
    public abstract void foo();
}

class RealBaseImpl extends BaseToInheritFrom {
    @Override
    public void foo() {
        // real impl
    }
}
s106mo
  • 1,243
  • 2
  • 14
  • 20
3

No, that's the whole point of an abstract method. What is your use case? Perhaps we can think about it based on the underlying need.

mjaggard
  • 2,389
  • 1
  • 23
  • 45
3

How about this: inside the default implementation of the method, use reflection to get the exact Class of the object. If the Class does not match your base class exactly, throw a RuntimeException or equivalent.

public class Parent {

    public void defaultImpl(){
        if(this.getClass() != Parent.class){
            throw new RuntimeException();
        }
    }

}
curioustechizen
  • 10,572
  • 10
  • 61
  • 110
  • It's a workaround that I've seen (in a similar way, at least) in SWT. It's a last resort, but a solution that would lead to a *compilation* error would certainly be better. – Joachim Sauer Oct 20 '11 at 07:58
  • 1
    Ah right.. I did not realize the OP was looking for a solution which would enforce this at compile time. And most certainly, a compilation error is any day better than a runtime exception. BTW, I have seen something similar in the Android APIs - they enforce that certain methods must call through to the `super` implementation, failing which a runtime exception is thrown. – curioustechizen Oct 20 '11 at 08:14
3

There's a reason it's not possible!

The derived class could simply call the base class's implementation when overriding the method.

So what's the point of forcing the class to override your method? I don't think there's any benefit.

Community
  • 1
  • 1
user541686
  • 205,094
  • 128
  • 528
  • 886
  • 1
    The conceptual reason is this: there *does* exist an annotation indicating that an overriding method must call the overridden one. Combining those two annotations allows you to create a method that does some basic work that must be the same for all subclasses, but not enough, because you already know that's not going to be enough, and you want to be sure that the subclass remembers to finish the job. – dfeuer Mar 31 '14 at 01:57
  • @dfeuer: How could you possibly prevent a situation of the derived class "calling" the base class method like `if (false) super.Foo();`? – user541686 Mar 31 '14 at 02:00
  • 1
    the intention (or at least *my* intention when I went searching for this question) was not to make sure no one broke it on purpose, but to make sure no one broke it by mistake! – dfeuer Mar 31 '14 at 02:12
  • 1
    @dfeuer: Oh I see, interesting... I got the impression the question was really about enforcement. For preventing mistakes, I'm not sure, it might've been a nice feature. I guess in Java they wanted to keep it simple when it's not totally necessary? – user541686 Mar 31 '14 at 02:46
2

Answer would be a no. You can redesign using template design pattern. It may help you.

Alternatively, you can make your child classes implement an interface. The interface may or may not be implemented by the super class.

Ravi Bhatt
  • 3,147
  • 19
  • 21
  • you can't "force" all child classes of the base class to implement an interface that the base class does not implement. And, if the base class didn't implement the interface, but had a named method that would satisfy the contract (meeting the LSP), then the interface on the derived class would be met by virtue of the existence of the base class's method. – KeithS Oct 20 '11 at 14:46
1

You can always make the base class have a method that throws an exception.

Technically the base class has defined the method, but it is not usable without overriding the method. In such a case, I prefer a runtime exception as they don't require an explicit throws statement. An example follows

public class Parent {

  public void doStuff() {
    throw new RuntimeException("doStuff() must be overridden");
  }

}

public class Child extends Parent {

  @Override
  public void doStuff() {
    ... all is well here ...
  }

}

The downside is that this doesn't prevent creation of Base objects; however, anyone attempting to use one of the "must be overridden" methods will soon find that they should have overridden the class.

While this solution meets the description of the request well, your application would probably benefit from not requiring a solution like this one. It's much better to avoid runtime crashes with compiler checks, which is what the abstract keyword provides.

Edwin Buck
  • 69,361
  • 7
  • 100
  • 138
1

I will mirror the other answers and say that there is no compiler-enforced way to force derived classes to override a non-abstract method. The whole point of making a method abstract is to define that a method with this signature must exist, but cannot be specified at the base level and therefore must be specified at a derived level. If there is a working, non-trivial implementation (as in it's not empty and doesn't just throw an exception or show a message) of a method at the base level, then this isn't strictly necessary in order for a call to the method from a consumer of the derived class to succeed. So, the compiler doesn't have to enforce overriding a method that can run quite successfully on either the base or derived levels.

In situations where you would want a derived class to override your working implementation, it should be pretty obvious that the base implementation doesn't do what the derived class's consumers will want; the base class either doesn't have enough implementation, or the wrong one. In those cases, you have to trust that a programmer deriving from your class will know what he is doing and thus know that the method needs to be overridden because it does not produce the right answer in the context of using his new object.

I can think of one thing you could do. It would require an abstract base, with a sealed (final for the Javaheads) "default" implementation. That way, there is a basic implementation of the method that is readily available to use as if it were a "base" class, but in order to define a different class for a new scenario, you must go back to the abstract class, and are thus forced to reimplement the method. This method could be the only abstract thing on the class, thus still allowing you to make use of basic implementations of other methods:

public abstract class BaseClass
{
   public abstract void MethodYouMustAlwaysOverride();

   public virtual void MethodWithBasicImplementation() { ... }
}

public final class DefaultClass:BaseClass
{
   public override void MethodYouMustAlwaysOverride() { ... }

   //the base implementation of MethodWithBasicImplementation 
   //doesn't have to be overridden
}

...

public class DerivedClass:BaseClass
{
   //Because DefaultClass is final, we must go back to BaseClass,
   //which means we must reimplement the abstract method
   public override void MethodYouMustAlwaysOverride() { ... }

   //again, we can still use MethodWithBasicImplementation, 
   //or we can extend/override it
   public override void MethodWithBasicImplementation() { ... }
}

However, this has two drawbacks. First, because you do not have access to DefaultClass's implementation through inheritance, you cannot extend DefaultClass's implementation, meaning that to do what DefaultClass does, plus a little more, you must rewrite the code from DefaultClass, violating DRY. Second, this only works for one level of inheritance, because you cannot force overriding if you allow inheritance from DerivedClass.

KeithS
  • 70,210
  • 21
  • 112
  • 164
1

maybe this helps:

class SuperClass {

    void doStuff(){

        if(!this.getClass().equals(SuperClass.class)){

            throw new RuntimeException("Child class must implement doStuff Method");
        }else{
            //ok
            //default implementation
        }
    }
}

class Child extends SuperClass{

    @Override
    void doStuff() {
        //ok
    }
}

class Child2 extends SuperClass{

}


 new SuperClass().doStuff(); //ok
 new Child().doStuff();         //ok
 new Child2().doStuff();        //error
Rodrigo
  • 5,435
  • 5
  • 42
  • 78
0

It may not be recommended, but you can throw an exeption( something like MethodeMustBeOverRiddenExp) in your methode implementation. Of course it is RunTime forcing but may be better than nuthing.

Itay wazana
  • 229
  • 2
  • 9
0

ok, let's learn it this way. I adhere to java style guidelines and use java syntax. So it is assumed that multiple inheritance and C++ templates are unavailable.

making the parent class method abstract is not a must, in OOP you use the concept of polymorphism. you can use the same method in two or more different ways. This is called method overriding.

let's take an example.

    public class Animal{
       public void makeSound(){
          System.out.println("Animal doesn't know how to make sound");
       }

    }

    public class PussyCat extends Animal{
        public void makeSound(){

           System.out.println("meowwww !!!");
        }

        public static void main(String args[]){
           PussyCat aCat=new PussyCat();
           aCat.makeSound(); 
        }
    }

this will print "meowww !!!" on the screen.

but this doesn't imply that the method makeSound must be overridden in the child class.

If you need the child class to be forced to override the methods, you better implement an interface by the class.

      public Interface audible{
         public void makeSound();

      }

      public class pussyCat implements audible{
          // now you must implement the body of makeSound method here
          public void makeSound(){
            System.out.println("meowwww !!!"); 
          }

          public static void main(String args[]){
           PussyCat aCat=new PussyCat();
           aCat.makeSound(); 
        }
      }

this will also print "meowwww !!!" on the screen

Tharindu Rusira
  • 691
  • 9
  • 17