假设我有一些方法的接口,如下所示:
interface Task {
void before();
void doStuff();
void after();
}
在这里,我将实现其中的一部分:
abstract class PoliteTask implements Task{
@Override
public void before() {
System.out.println("Hey");
}
@Override
public abstract void doStuff();
@Override
public void after() {
System.out.println("Cya");
}
}
现在我想确保在所有扩展类中调用那些before()
和after()
实现。
这里我们有一个需要在before()
中初始化的类:
class ActualStuffTask extends PoliteTask {
private int fancyNumber;
@Override
public void before() {
// init some things
fancyNumber = 42;
}
@Override
public void doStuff() {
System.out.println("Look, a number: "+fancyNumber);
}
}
显然,ActualStuffTask
会覆盖before()
,因此它不会说“嘿”,只会说“Cya”。
如果我在PoliteTask
final
中创建方法,这不会发生,但是它的子类无法覆盖方法。
在super.before()
中调用ActualStuffTask
会有效,但无论子类实现如何,我都希望保证这种效果。
问题是:
我应该使用什么模式来同时实现父实现和子实现?
答案 0 :(得分:5)
我喜欢使用您在实现类中实现的抽象方法。
abstract class PoliteTask implements Task{
@Override
public final void before() {
System.out.println("Hey");
doBefore();
}
protected abstract void doBefore();
protected abstract void doAfter();
@Override
public abstract void doStuff();
@Override
public final void after() {
System.out.println("Cya");
doAfter();
}
}
class ActualStuffTask extends PoliteTask {
private int fancyNumber;
@Override
protected void doBefore() {
// init some things
fancyNumber = 42;
}
@Override
public void doStuff() {
System.out.println("Look, a number: "+fancyNumber);
}
@Override
protected void doAfter() {
// something else
}
}
请注意,Task
方法是final
。他们不需要。这取决于您构建API的方式。
答案 1 :(得分:3)
这种情况的常用方法是这样的(简化示例):
abstract class Base {
public final void before() {
System.out.println("Hey");
doBefore();
}
protected void doBefore() {
}
}
这样基本代码总是会被执行,子类可以添加它们的实现。
答案 2 :(得分:1)
您可以关注template method pattern。在final
(例如AbstractClass
)中创建一个doAll
方法,按顺序调用其他方法:
public final void doAll() {
before();
doStuff();
after();
}
然后,您可以使before
和after
成为final
方法,这样它们将始终由子类执行,并且无法更改其行为。
答案 3 :(得分:1)
一种选择是明确调用super.before()
课程中的ActualStuffTask
:
@Override
public void before() {
super.before();
// init some things
fancyNumber = 42;
}
另一种选择是更改父类的设计,并使用before
关键字“保护”final
方法:
abstract class PoliteTask implements Task {
@Override
public final void before() {
System.out.println("Hey");
internalBefore();
}
protected abstract void internalBefore(); // child class should override this method
...
}