抽象类中的可选方法实现

时间:2017-01-26 21:58:08

标签: java interface java-8 abstract

我正在研究一些框架,我得到了一个抽象类,应该实现它。

现在我得到了一些用户应该能够配置的其他内容,但它是可选的。

所以不是抽象方法:

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();
}

我想过只检查接口实现:

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();
}

因此,如果有人使用接口Log实现AbstractModule,它也会显示消息。我看到的实现者的好处是:她不需要关心实现logMessage(),就像在第一个例子中那样。这是一种有效的方法还是应该以不同的方式完成?

提前致谢!

祝你好运

3 个答案:

答案 0 :(得分:5)

我会将Logger作为模块的一个组件,并在抽象类中定义一个默认的no-op logger。这样你就可以摆脱instanceof并保持灵活性。

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();
}

这是一个扩展AbstractModule的示例类:

public class Module extends AbstractModule{

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

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

}

如果要公开记录器,可以在抽象类中为记录器定义一个getter方法:

public Log getLogger(){
    return log;
}

答案 1 :(得分:5)

由于此问题已标记为java-8,因此备用解决方案是使用interfacedefault方法:

public interface Module {
    public default void doSomething() {
        if (logMessage() != null)
            System.out.println(logMessage());
        doStuff();
    }

    public default String logMessage() { return null; } // I'm optional
    public void doStuff();
}

用法:

class NoLogModule implements Module {
    @Override
    public void doStuff() { }
}

class LogModule implements Module {

    @Override
    public void doStuff() { }

    @Override
    public String logMessage() { return "Message "; }

}

使用此方法而不是 Abstract 类的一个优点是您的类现在可以从另一个类扩展。这种方法的一个缺点是,你无法阻止某人覆盖 doSomething方法(基于你的代码,它看起来你不关心这个)

答案 2 :(得分:2)

到达KeyDown有点代码味道;这通常是一种更好的方式。

我的第一直觉是在基类中使用no-op方法:

instanceof

显然什么也没做;但是你可以在子类中重写:

class AbstractModule {
  final void doSomething() {
    maybeLogMessage();
  }

  void maybeLogMessage() {}
}

会打印信息。

如果您不想在所有子类中重复class Subclass extends AbstractModule { @Override void maybeLogMessage() { System.out.println("The message"); } } ,则可以从方法返回一个特殊值,以表明它不应该被记录。例如,您可以要求字符串为非空:

System.out.println