Optional method implementation in an abstract class

user7476057 :

I'm working on some framework and I got an abstract class, which should be implemented.

Now I got some other stuff the user should be able to configure, but it is optional.

So instead of the abstract method:

public abstract class AbstractModule {
    public void doSomething() {
        if (logMessage() != null)
            System.out.println(logMessage());
        doStuff();
    }

    protected abstract String logMessage(); // I'm optional
    protected abstract void doStuff();
}

I thought of just checking for an interface implementation:

public interface Log {
    String logMessage();
}

public abstract class AbstractModule {
    public void doSomething() {
        if (this instanceof Log) {
            if (((Log) this).logMessage() != null)
                System.out.println(((Log) this).logMessage());
        }
        doStuff();
    }

    protected abstract void doStuff();
}

So, if someone is implementing AbstractModule with the interface Log it would also show the message. The benefit for the implementer that I see: She doesn't need to care about implementing logMessage(), as it would be in the first example. Is this a valid approach or should it be done differently?

Thanks in advance!

Best regards

Calculator :

I would make the Logger a component of your module and define a default no-op logger in the abstract class. This way you get rid of the instanceof and still preserve the flexibility.

interface Log {
    void logMessage();
}

public abstract class AbstractModule {
    protected Log log;

    public AbstractModule(){
        this.log = () -> {};
    }

    public AbstractModule(Log log){
        this.log = log;
    }

    public void doSomething() {        
        log.logMessage();        
        doStuff();
    }

    protected abstract void doStuff();
}

Here is an example class extending AbstractModule:

public class Module extends AbstractModule{

    public Module(){
        super(() -> System.out.println("message"));         
    }

    @Override
    protected void doStuff() {
        // do stuff     
    }   

}

You can define a getter-method for the logger in the abstract class if you want to expose the logger:

public Log getLogger(){
    return log;
}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=453188&siteId=1