Question

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.)

Was it helpful?

Solution

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.

OTHER TIPS

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().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top