Is there a way to make a method which is not abstract but must be overridden?
Solution 1
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.
Solution 2
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
}
}
}
Solution 3
Consider making an interface with this method. Class descendants will have to implement it.
Solution 4
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
}
}
Solution 5
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();
}
}
}
Admin
Updated on June 25, 2022Comments
-
Admin almost 2 years
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 over 12 yearsHow 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 over 12 yearsIt'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.
-
curioustechizen over 12 yearsAh 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. -
Anthony over 12 yearsI 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 inheritingBase
and notDefaultBase
. Otherwise, this is a great work-around I think. -
Ivan Nikitin over 12 yearsThere 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.
-
KeithS over 12 yearsyou 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.
-
Visionary Software Solutions over 12 yearsNicely done. This is probably the most elegant way of dealing with this issue.
-
Dave over 12 yearsThis is the better way because it's bad design to override methods that have definitions. All methods should be final, abstract, or empty.
-
dfeuer about 10 yearsThe 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.
-
user541686 about 10 years@dfeuer: How could you possibly prevent a situation of the derived class "calling" the base class method like
if (false) super.Foo();
? -
dfeuer about 10 yearsthe 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!
-
user541686 about 10 years@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?
-
Syed Aqeel Ashiq almost 2 yearsAah I want to mark this as accepted this answer, but my old SO account is lost :'(