Can I tell if an abstract method has been called? - java

Given this class:
abstract class Foo{
public Foo(){...}
public abstract void checkable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
Is there any code I can put in Foo's constructor to make calledWhenCheckableIsCalled get called when checkable is called?
Note: This is a gross simplification of an actual project I am working on.
Edit: I have already implemented a template pattern workaround. I just wondered if there was another way to do this I am missing. (Perhaps using reflection.)

Looks like a template method pattern.
But then you must implement Foo.checkable() and introduce another abstract method to delegate to.
abstract class Foo{
public Foo(){}
public void checkable(){
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
public void calledWhenCheckableIsCalled(){
System.out.println("checkable was called");
}
}
I would also suggest to make checkable() final in this case so that you can be sure that checkable() can not implemented in another way as you expected.
In addition to Brian Roach's comment
The downside is that the protected can be expanded to public in the subclass, so you can't explicitly enforce it.
That's true, but you can prevent a Foo instance from being instantiated if a subclass increases the visibility of doCheckable. Therefore you have to introduce a verification whenever an object is instantiated. I would recommend to use an initializer code so that the verification is executed on every constructor that exists. Then it can not be forgotten to invoke and therefore be by-passed.
For example:
abstract class Foo {
{ // instance initializer code ensures that enforceDoCheckableVisibility
// is invoked for every constructor
enforceDoCheckableVisibility();
}
public Foo() {...}
public Foo(Object o) {...}
private void enforceDoCheckableVisibility() {
Class<?> currentClass = getClass();
while (currentClass != Foo.class) {
try {
Method doCheckableMethod = currentClass.getDeclaredMethod("doCheckable");
if (Modifier.isPublic(doCheckableMethod.getModifiers())) {
throw new RuntimeException("Visibility of "
+ currentClass.getSimpleName()
+ ".doCheckable() must not be public");
}
} catch (SecurityException | NoSuchMethodException e) {}
currentClass = currentClass.getSuperclass();
}
}
}
Since the check is implemented using reflection the downside is that it is only checked at runtime. So you will not have compiler support of course. But this approach let you enforce that an instance of a Foo can only exist if it fulfills your contract.

No, the constructor will get invoked once during the object initialisation. You can however get your subclass that provides the implementation to call the method in the super class:
class Bar extends Foo {
// implementation of abstract method
public void checkable(){
super.calledWhenCheckableIsCalled(); // call to parent's method
...
}
}
EDIT
You could achieve this with aspects. Using an aspect you can intercept each call to a method by referring to the abstract parent method. This leaves you free from interfering eith the child code. Your calledWhenCheckableIsCalled code would then become part of the intercepting code.
abstract class Foo {
// use pointcut to intercept here
public void checkable();
}

There is no way as you are forcing that method to implement in child.
An awkward suggestion will be know from child implementation. I mean there is no clean way AFAIK

abstract class foo {
public abstract void bar();
public void moo() {
System.out.println("some code");
this.bar();
System.out.println("more code");
}
}
now if moo is called, the underlying implementation of bar will be used, it is just a small paradigm shift from what you want.
so your end user would call moo instead of bar, but he still needs to implement bar

Nope, an abstract method doesn't have a body. You could, however, chain your method like this:
abstract class Foo {
void callMeInstead() {
// do common
callMeImplementation();
}
abstract void callMeImplementation();
}

It looks to me like you're looking for the template pattern:
public abstract class Template {
public final void checkable() {
calledWhenCheckableIsCalled();
doCheckable();
}
protected abstract void doCheckable();
private void calledWhenCheckableIsCalled() {
System.out.println("checkable was called");
}
}
Now, each time checkable() is called, calledWhenCheckableIsCalled() is also called. And the suclass must still provide the actual implementation of checkable(), by implementing the doCheckable() method.
Note that making checkable() final prevents a subclass from overriding it and thus bypassing the call to calledWhenCheckableIsCalled().

Related

Can an overriding method have a different access specifier from that in the base class?

Which access modifier, in an abstract class, do I have to use for a method,
so the subclasses can decide whether it should be public or not? Is it possible to "override" a modifier in Java or not?
public abstract class A {
??? void method();
}
public class B extends A {
#Override
public void method(){
// TODO
}
}
public class C extends B {
#Override
private void method(){
// TODO
}
}
I know that there will be a problem with static binding, if
someone calls:
// Will work
A foo = new B()
foo.method();
// Compiler ?
A foo = new C();
foo.method();
But maybe there is another way. How I can achieve that?
It is possible to relax the restriction, but not to make it more restrictive:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method(){ // OK
}
}
public class C extends A {
#Override
private void method(){ // not allowed
}
}
Making the original method private won't work either, since such method isn't visible in subclasses and therefore cannot be overriden.
I would recommend using interfaces to selectively expose or hide the method:
public interface WithMethod {
// other methods
void method();
}
public interface WithoutMethod {
// other methods
// no 'method()'
}
public abstract class A {
protected void method();
}
public class B extends A implements WithMethod {
#Override
public void method(){
//TODO
}
}
public class C extends B implements WithoutMethod {
// no 'method()'
}
... then only work with the instances through the interfaces.
When overriding methods, you can only change the modifier to a wider one, not vice versa. For example this code would be valid:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
public void method() { }
}
However, if you try to narrow down the visibility, you'd get a compile-time error:
public abstract class A {
protected void method();
}
public class B extends A {
#Override
private void method() {}
}
For your case, I'd suggest to make C not implementing A, as A's abstraction implies that there's a non-private method():
public class C {
private void method(){
//TODO
}
}
Another option is to make the method() implementation in C throwing a RuntimeException:
public class C extends A {
#Override
public void method(){
throw new UnsupportedOperationException("C doesn't support callbacks to method()");
}
}
What you are asking for is not possible for very good reasons.
The Liskov substitution principle basically says: a class S is a subclass of another class T only then, when you can replace any occurrence of some "T object" with some "S object" - without noticing.
If you would allow that S is reducing a public method to private, then you can't do that any more. Because all of a sudden, that method that could be called while using some T ... isn't available any more to be called on S.
Long story short: inheritance is not something that simply falls out of the sky. It is a property of classes that you as the programmer are responsible for. In other words: inheritance means more than just writing down "class S extends T" in your source code!
This is impossible because of the polymorphism. Consider the following. You have the method in class A with some access modifier which is not private. Why not private? Because if it was private, then no other class could even know of its existence. So it has to be something else, and that something else must be accessible from somewhere.
Now let's suppose that you pass an instance of class C to somewhere. But you upcast it to A beforehand, and so you end up having this code somewhere:
void somewhereMethod(A instance) {
instance.method(); // Ouch! Calling a private method on class C.
}
One nice example how this got broken is QSaveFile in Qt. Unlike Java, C++ actually allows to lower access privileges. So they did just that, forbidding the close() method. What they ended up with is a QIODevice subclass that is not really a QIODevice any more. If you pass a pointer to QSaveFile to some method accepting QIODevice*, they can still call close() because it's public in QIODevice. They “fixed” this by making QSaveFile::close() (which is private) call abort(), so if you do something like that, your program immediately crashes. Not a very nice “solution”, but there is no better one. And it's just an example of bad OO design. That's why Java doesn't allow it.
Edit
Not that I missed that your class is abstract, but I also missed the fact that B extends C, not A. This way what you want to do is completely impossible. If the method is public in B, it will be public in all subclasses too. The only thing you can do is document that it shouldn't be called and maybe override it to throw UnsupportedOperationException. But that would lead to the same problems as with QSaveFile. Remember that users of your class may not even know that it's an instance of C so they won't even have a chance to read its documentation.
Overall it's just a very bad idea OO-wise. Perhaps you should ask another question about the exact problem you're trying to solve with this hierarchy, and maybe you'll get some decent advises on how to do it properly.
Here is a part of the #Override contract.
The answer is : there isn't any possibility to achieve what you have.
The access level cannot be more restrictive than the overridden
method's access level. For example: if the superclass method is
declared public then the overridding method in the sub class cannot be
either private or protected.
This is not a problem concerning abstract classes only but all classes and methods.
THEORY:
You have the determined modifiers order:
public <- protected <- default-access X<- private
When you override the method, you can increase, but not decrease the modifier level. For example,
public -> []
protected -> [public]
default-access -> [public, default-access]
private -> []
PRACTICE:
In your case, you cannot turn ??? into some modifier, because private is the lowest modifier and private class members are not inherited.

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.

Good method to make it obvious that an overriden method should call super?

This problem just bit me, its pretty easy to forget to call super() when overriding a method.
In my case I was refactoring some existing stuff where there were already about ten classes overriding a method. Until yesterday the method had an empty default implementation, so it didn't matter if subclasses called super or not.
You can find the overriders just fine with any IDE worth its salt, but you know how it is, phone rings, colleagues have a smalltalk behind you back... its easy to forget to check a place or otherwise overlook it.
Ideally there would be a counterpart for the #Override annotation and the compiler would generate a warning for those places if the base class method is annotated but the override doesnt call super.
Whats the next best thing I can do?
Not quite elegant, but possible solution is to break that method into two:
public abstract class Foo {
public void doBar() {
// do your super logic
doBarInternal();
}
public abstract void doBarInternal();
}
If the superclass implementation MUST ALWAYS be called you could use the 'template method' pattern.
So what you have now is something like:
public static class Parent {
public void doSomething() {
System.out.println("Parent doing something");
}
}
public static class Child extends Parent {
public void doSomething() {
// MUST NOT FORGET SUPER CALL
super.doSomething();
System.out.println("Child doing something");
}
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
And this would become:
public abstract static class Parent {
public final void doSomething() {
System.out.println("Parent doing something");
childDoSomething();
}
public abstract void childDoSomething();
}
public static class Child extends Parent {
public void childDoSomething() {
System.out.println("Child doing something");
}
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
(classes are made static for easy testing within one class)
I made doSomething final to avoid it being overridden since in this solution childDoSomething should be implemented instead.
Of course this solution means Parent can no longer be used as a concrete class.
EDIT: after reading comments about Child implementing a third party interface; this does not need to be a problem:
public interface ThirdPartyInterface {
public void doSomething();
}
public abstract static class Parent {
public final void doSomething() {
System.out.println("Parent doing something");
childDoSomething();
}
public abstract void childDoSomething();
}
public static class Child extends Parent implements ThirdPartyInterface{
public void childDoSomething() {
System.out.println("Child doing something");
}
// public final void doSomething() {
// // cannot do this because Parent makes it final
// }
}
public static void main(String[] args) {
Child child = new Child();
child.doSomething();
}
Loooking for something else I found interesting OverrideMustInvoke annotation in FindBugs:
http://findbugs.sourceforge.net/api/edu/umd/cs/findbugs/annotations/OverrideMustInvoke.html
If you do not insist on compile time safety you could use a mechanism that throws an exception whenever a subclass does not behave as logically required: How do I force a polymorphic call to the super method?
I have 2 different suggestions:
1) Build a junit test that discovers all subclasses of your base class, and then selects all the methods decorated with the #Override annotations. I have some unit tests that do something similar (i.e. find all subclasses, check that they truly are Serializable for example).
Unfortunately, the verification of whether they call "super" is a little less straightforward. You would either need to have the test look up the source file, and search it, or better (but I don't know how to do this), read the byte code and see if you can detect the call to super.
2) Needing to guarantee a call to super is probably an indicator of a design/interface issue, rather than a coding/implementation issue. If you really want to guarantee that users call super, it would be better to make the super class abstract, clearly designate an abstract implementation method for them to override, and have the super control the flow of execution.
If you want to define a default implementation, so that not all users need to subclass provide implement that method, you could define a default implementation class for people to use. (And if you really want to control it, define that default class implementation method as final to force them to go back to subclassing the abstract parent.)
Code reuse inheritance is always harder to manage, and so it needs to be done carefully. Anyone doing code reuse inheritance has to have a good idea of the internals of the super class to do it right (which is a bit yucky). For example, do you have to call super.method() at the beginning of your overriding code, or at the end? (or could you do it in the middle...)
So in summary, the best solution is to try avoid a design where you have to enforce that.
What could work - creating some marker annotation (i.e. #MustCallParent) and then create some annotation processor to check that methods marked with it comply to the constraint.

Categories

Resources