Enforce super call on non constructor methods - java

Is it possible to enforce an overriden method to call the superclass method? Constructors always need to call their superclass constructor. But i want to enforce this on normal methods, without the position of when it is called mattering.
Example:
public class A {
public void doSth() {
System.out.println("I must appear on console!");
}
}
public class B extends A {
#Override
public void doSth() {
System.out.println("Bla!"); // IDE should mark an error, because supermethod is not called.
}
}

No, that is not possible. It is entirely up to the overriding method to call the superclass method, or not.
However, there is a way to do it, if you want to enforce control.
This is called the Template Method Pattern. Whether the template methods are abstract or stubs (like shown here), depends on whether they must do something, or simply allow something extra to be done.
public class A {
public final void doSth() { // final, preventing override by subclasses
beforeDoSth();
System.out.println("I must appear on console!");
afterDoSth();
}
protected void beforeDoSth() { // protected, since it should never be called directly
// Stub method, to be overridden by subclasses, if needed
}
protected void afterDoSth() {
// Stub method, to be overridden by subclasses, if needed
}
}
public class B extends A {
#Override
protected void afterDoSth() {
System.out.println("Bla!");
}
}
If you then execute new B().doSth(), you'll get:
I must appear on console!
Bla!

No, it is not possible. If you allow a method to be overridden at all (by not declaring it or its class final) then you cannot control much of anything about the implementation of methods that override it. You can, however, document that such methods should invoke the superclass's version. There's only so much you can do to protect your users from themselves.
You may also find that there are alternative designs that would suit you better. For example, if you want to allow subclasses to override particular details of a computation, but not to override the whole computation altogether, then you could employ the Template Method pattern. In that case, the computation is driven by one "template" method, which you can declare private or final if you wish, and the customizable details are implemented in a separate, non-final, public or protected, possibly abstract method that the driver method calls where appropriate.

Although not strictly Java related, I was looking for an answer to this issue as it relates to Android and found the annotation in the support annotations library called "#CallSuper". It does exactly what you think, and throws a lint error if the subclass does not call the super's implementation of methods annotated with #CallSuper.
That solved my usecase, but again, I know that the solution is strictly tied with Android. Please let me know if that is too far off base and I will remove the answer.
Here is some more documentation on #CallSuper.
https://developer.android.com/reference/android/support/annotation/CallSuper.html
https://developer.android.com/studio/write/annotations.html (just search for CallSuper and it'll show right up in that second link.

No, it is not possible. It is up to the overriding method to call or to not call the method that it overrides.

Yes, it's possible, given the following constraints:
The method has a non-void return type
Subclasses (or other classes accessible by the subclasses) cannot create instances of the return type
As #Andreas pointed out, the super call could still be avoided by returning null. In practice, this shouldn't be a problem, but it's reasonable to enforce non-nullness in the contract (super class documentation) and also by using a null-preventing annotation, e.g. #Nonnull, so that any modern IDE can give a compile error when the super class method is not called.
For example:
import javax.annotation.Nonnull;
public class A {
public static final class Result {
private Result() {
// declare constructor private so the class cannot be
// instantiated from outside
}
}
/**
* Does something.
*
* #return the result; never {#code null}
*/
public #Nonnull Result doSth() {
System.out.println("I must appear on console!");
return new Result();
}
}
//...
public class B extends A {
#Override
public #Nonnull Result doSth() {
System.out.println("Bla!");
// only way to get a Result instance is through super.doSth()
Result res = super.doSth();
/* manipulate the result as needed */
return res;
}
}

Related

Abstract class non abstract method invoke

This seems to be basic question. But worth to clarify before interviews.
I have a non abstract method in abstract class. Its concrete class overridden that method. But I want to call the parent class's original method to invoke rather than overridden method. Is there any way to do it ?
As I can understand there's no way to invoke original method ?
public abstract class Testabstract {
public void t1() {
System.out.println("parent");
}
}
public class Testconcrete extends Testabstract {
public void t2() {
System.out.println("child11");
}
public void t1() {
System.out.println("childss");
}
}
public class Main {
public static void main(String[] args) {
Testconcrete a = new Testconcrete();
a.super.t1();// compile error
a.t2();
}
}
No, you can't directly invoke the superclass's overridden method. This is by design; the subclass might add some sort of behavior that is necessary for correctness (such as maintaining some sort of cache or other data structure) or functional requirements (such as logging). Bypassing the subclass's functionality would put the correctness of the model at risk and breaks the encapsulation that assures it.
super keyword can use only with in the child class.
For ex you can try doing
public void t2() {
super.t1();
System.out.println("child11");
}
Casting to Parent also won't work still your underlying element is Child.
So you cannot access from outside of Child class in a clean way. Don't exactly know if they is any naive way to do that.
Your understanding is correct. Without changing one of classes Testabstract or Testconcrete there is no way to invoke the original method on an instance of Testconcrete.
I don't think it's even possible to do it with reflection.

Force a subclass to override both methods or none

Say I have a base class with a pair of methods (called foo and bar). In most cases, they don't need to be overriden, but in some cases, they do. I want to make sure if one of them is overriden, then the other one must also be overriden, or it is an error.
What tricks could I use to ensure either none of the two methods is overriden, or both of them are overriden?
This has proven to be an interesting thought exercise. The best solution I could come up with is as follows:
Declare an interface for your methods:
public interface YourInterface {
public void methodOne();
public void methodTwo();
}
Create a base class that implements these methods by delegating to an inner YourInterface instance. Take a parameter in your protected constructor that overrides the default behaviour:
public abstract class Base implements YourInterface {
private YourInterface override;
protected Base(YourInterface override) {
this.override = (override == null) ? new BaseImplementation() : override;
}
#Override
public final void methodOne() {
override.methodOne();
}
#Override
public final void methodTwo() {
override.methodTwo();
}
// This is the default implementation
private static class BaseImplementation implements YourInterface {
#Override
public void methodOne() {
System.out.println("Original one.");
}
#Override
public void methodTwo() {
System.out.println("Original two.");
}
}
}
The two methods are final in the base class, so subclasses can't just override one of them.
Not necessarily an elegant or advisable solution.
There is no easy way to do this. A method exists, but I don't know if it will really meet your needs. I think what you should really consider is why you want this, and if a different construct (abstract classes? AOP? Something else?) will meet your design needs better.
You can write a snippet to quickly determine if a method has been overridden:
String declaredIn = obj.getMethod("myMethod").getDeclaringClass();
This will return the current class name if overridden, or a/the base class name if not.
If you require any subclasses to call super.foo and super.bar in foo and bar (which you can enforce with stuff like non-parameterless constructors), you can enforce this in the base methods: check if the declaring class is the same for both methods, and throw an exception.
A similar problem exists in Object, with the equals(Object) and hashCode() methods.
If you want to absolutely ensure that an implementation is provided for either both or neither, Duncan's answer provides an elegant solution for this by wrapping the functionality in an interface to be passed in during construction - it guarantees either the default implementation for both methods, or a different implementation for both.
However, if your case is more like the one in Object, where they dont' need to be overridden, but just satisfy a very specific contract, then clear documentation on what that contract is will work better, allowing developers to satisfy the contract the way they determine is best.
If you had one method and you wanted to make sure it was overridden, I think something like this would work:
public class C {
public void foo() {
if (this.getClass() != C.class)
throw new RuntimeException ("foo was not overridden for class " + this.getClass().getName());
...
But making sure two methods are either both overridden or not overridden seems much trickier. How about this: Instead of having child classes override foo and bar, make foo and bar final methods, and provide protected "implementation" methods in which classes must override either both or neither. Then:
public class C {
private boolean fooCalled = false;
private boolean barCalled = false;
private boolean fooDefault = false;
private boolean barDefault = false;
public final void foo() {
fooCalled = true;
fooImpl();
checkOverrides();
}
public final void bar() {
barCalled = true;
barImpl();
checkOverrides();
}
private void checkOverrides() {
if (this.getClass() != C.class && fooCalled && barCalled &&
(fooDefault != barDefault))
throw new RuntimeException ("foo or bar was overridden without the other for class " + this.getClass().getName();
}
protected void fooImpl() {
fooDefault = true;
// the rest of the default implementation
}
protected void barImpl() {
barDefault = true;
// the rest of the default implementation
}
}
We can't check until both foo and bar have been called at least once each (and if either of those is never called, then it shouldn't matter whether it's overridden or not). Once both have been called, we will know whether or not each method (the "Impl" version) was overridden, because a flag will be set when the default implementation is called. Then we can do whatever checking we wish with the information.
This will fail if an overriding fooImpl calls super.fooImpl() (similarly for bar), but my guess is that if you expect this to happen, then the requirement that both be overridden if one is probably doesn't make sense. If it's still necessary, a separate protected default implementation method could be provided that doesn't set the fooDefault flag, and clients will just have to be careful to use it instead of the super method.
Having written all this, it's hard for me to imagine that a solution like this would be really necessary. Maybe you have a case where it's worthwhile.
You can add a contructor to your class and use reflection to check in wich class the methods are overrided and throw an Error if it's only one overrided.
Can be something like this (test is the name of the base class that I used):
public test() {
Class clazz = this.getClass();
try {
Method m = clazz.getMethod("foo", new Class[]{});
Class cFoo = m.getDeclaringClass();
m = clazz.getMethod("bar", new Class[]{});
Class cBar = m.getDeclaringClass();
if (cFoo.equals(test.class)&&!cBar.equals(test.class)) throw new Error();
if (!cFoo.equals(test.class)&&cBar.equals(test.class)) throw new Error();
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
Have a marker interface #OverrideRequired with target METHOD
Annotate needed methods with #OverrideRequired.
Use Reflection to write validateOverrideRequired(Class...classes) which throws a RuntimeException if the methods with annotations #OverrideRequired are not overridden in the subclass? Call it once per build as a rule.
The above is just a concept; not sure of the implementation.
But an interesting question & equally interesting answers (rest) from the group.
Can't you put both of them into an interface and let the client decide whether to implement them or not.
This way either both of them are overridden if some implements this interface or not if no one implements

Java method extension instead of overwriting

Is there some type of #annotation, or other method, in Java to enforce method extension, instead of overriding?
To be specific, let's say I have a class Foo:
class Foo {
public void bar(Thing thing) {
// ...
}
}
Is there a way I can enforce, at compile time, that any class X that extends Foo, and also overrides bar, makes a call to super.bar(thing) first?
No, you have to explicitly write it.
Side note for constructors: the superclass' nullary constructor will be implicitly called when instantiating the subclass, however many parameters the latter's constructor has.
You could declare bar to be final, then call an abstract method from bar, which would force subclasses to implement an "extension".
abstract class Foo {
public final void bar(Thing thing) {
barImpl(thing);
overrideMe(thing);
}
private final void barImpl(Thing thing) {
// Original implementation of "bar" here.
}
protected abstract void overrideMe(Thing thing);
}
EDIT
I've changedoverrideMe from public to protected so users of Foo can't just call overrideMe instead of bar.
Generally, what you can do is to create a final method, that calls the extendable one.
class Foo {
#Override
public final void bar(Thing thing) {
// super code comes here
this.doBar(thing);
}
public abstract void doBar(Thing thing);
}
When you call
foo.bar(thing);
your super code runs first, then the code from the child class.
This way you can protect your full bar logic, and allow only certain parts to be extended/reimplemented.
Also, it allows you to postprocess the result, or to break up your code to certain subtasks.
While you cannot force code to call up to its superclass at compile time, it's not too hard to detect at run time when code does not call up to the superclass.
class Foo {
private boolean baseCalled;
public final void bar(Thing thing) {
baseCalled = false;
barImp(thing);
if (!baseCalled) {
throw new RuntimeException("super.barImp() not called");
}
}
protected void barImp(Thing thing) {
baseCalled = true;
. . . // base class implementation of bar
}
}
Note that this extends to multiple levels of inheritance without further elaboration. The method works particularly well for methods that are called from within Foo; in those cases, you can often forgo the final qualifier and redirection to an implementation method, and just define the base class method to set the flag. Clearing the flag would be done at each point of invocation.
The above pattern is used extensively in the Android framework. It doesn't guarantee that super.barImp was called as the first thing in subclass overrides; just that it was called.
You can try to use #AroundInvoke annotation, if you are using EJBs.
By using reflection, you can find the same method in your parent class, and yo can invoke it with the same parameters as the original method was called.
Note, that in this case you must avoid super.bar(thing) calls, otherwise they would be called twice.

Keep visibility of abstract method in subclass

I have following abstract class:
public abstract class AbstractCreateActionHandler {
protected IWorkItem mCurrentWI;
public AbstractCreateActionHandler(IWorkItem wi) {
this.mCurrentWI = wi;
}
public final void invoke() {
try {
if (checkForLockingFile()) {
this.executeAction();
Configuration.deleteInstance();
}
} catch (IOException e) {
Configuration.deleteInstance();
e.printStackTrace();
}
}
protected abstract void executeAction();
private boolean checkForLockingFile() throws IOException {
String path = Configuration.getInstance().getProperty("path");
File lock = new File(path + "lock_"+mCurrentWI.getId()+"__.tmp");
if(!lock.exists()) {
lock.createNewFile();
return true;
}
return false;
}
}
A sub class extends the abstract class:
public class MyAction extends AbstractCreateActionHandler {
public MyAction(IWorkItem wi) {
super(wi);
}
#Override
protected void executeAction() {
// Implementation
}
// ALSO POSSIBLE...
/* #Override
public void executeAction() {
// Implementation
}*/
}
Question:
Is it possible that a developer which extends the abstract class and implements executeAction() method is not allowed the change the visibilty of executeAction()?
At the moment a developer can simply change the visibilty of the method to "public", create an object of the subclass and invoke executeExtion(). The visibility modifier can be changed and the abstract method is still accepted as "implemented".
So the "normal" calling sequence and checks which are executed in abstract class method invoke() can be bypassed. Is there a way to check if the invoke() method was called?
No, there's not really a way to restrict that. are you worried about malicious developers or clueless coworkers? if the latter then you just need to establish coding conventions like "don't increase the visibility of methods" and put some javadoc on the abstract method indicating proper usage. if the former, then you probably need to design your code differently (possibly using the strategy pattern).
Is it possible that a developer which extends the abstract class and implements executeAction() method is not allowed the change the visibilty of executeAction()?
No, this is not possible.
Chapter 8.4.8.3. Requirements in Overriding and Hiding of the Java Language Specification specifies:
The access modifier (ยง6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows: ...
So it is always possible to have the overriding method provide more access than the overridden method in the parent class.
See also java access modifiers and overriding methods.
It is allowed to change the modifier to public because it does not violate the Liskov Substitution Principle.
So the "normal" calling sequence and checks which are executed in
abstract class method invoke() can be bypassed. Is there a way to
check if the invoke() method was called?
If you pass someone the reference to AbstractCreateActionHandler then the caller will not be able to see the method executeAction as it is not public in AbstractCreateActionHandler class. So the caller will not be able to bypass execution sequence if you pass reference to Base class to caller. If you pass reference to Concrete class then the sequence can be broken.

how to add a warning for not calling super() in Java/eclipse

I would expect subclass always call super() for some method.
How can I enforce or at least give a warning at compile time?
Thanks
You could engineer this a little differently to enforce the behaviour:
The super class should be abstract, or at least define the method final. Then define a protected method that the subclass will have to implement and finally have the super class call the method after completing whatever code needs to be run beforehand:
public abstract class SuperClass {
// final so it can't be overriden
public final void superMethod() {
// required code here
// then delegate to implMethod
implMethod();
}
protected abstract() void implMethod();
}
public class SubClasss extends SuperClass {
protected void implMethod() {
// sub class logic
}
}
Of course, SuperClass doesn't have to be abstract, you could implement the implMethod and then allow subclasses to override it
I think that Chris White's answer is best in the general case. But chen ying's comment "I know enforcing to call super is not good. But I did not own the super class. And SDK documentation requires to call super. for example link" suggests that it is not suitable in this particular instance.
I would thus suggest modifying Chris White's answer to meet the particulars.
class ChenYingTestCase extends ServiceTestCase
{
/**
* Gets the current system context and stores it.
* You can not extend this method.
* If you want to achieve the effect of extending this method,
* you must override chenYingSetupMethod.
**/
public final void setUp ( )
{
super.setUp ( ) ;
chenYingSetup ( ) ;
}
/**
* Does nothing (unless you extend it)
*
* Extend this method to do your
* own test initialization. If you do so, there is no need to call super.setUp()
* Hint: calling super.setUp() is probably a bad idea.
* as the first statement in your override.
* Just put your test initialization here.
* The real SetUp method will call super.setUp() and then this method.
**/
protected void chenYingSetUp ( )
{
}
}
Then if a subclass is under your control make it a subclass of ChenYingTestCase. If the subclass is not under you control, well you can't really force it to call super().
If the base class has a default (parameterless) constructor, it will always be called automatically if no explicit super() call is given. If you have control over the base class, you can make the default constructor private:
public abstract class Whatever {
private Whatever() {
// not visible to subclasses
}
public Whatever(A a, B b, ...) {
// this constructor must always be explicitly called by subclasses
}
}
Barring that, your IDE may allow you to turn on a warning for this. It would be somewhere in the options menus. If you don't see it, it's not there.
Long time, stuff changed. By now (almost 9 years later) there is a #CallSuper annotation you can add the base method to enfore that any class overwriting this method has to call super. See here for more info.

Categories

Resources