Java 强制重写两个方法中的一个
我有一种类型的对象,称之为Java 强制重写两个方法中的一个,java,design-patterns,overriding,abstract-class,optional,Java,Design Patterns,Overriding,Abstract Class,Optional,我有一种类型的对象,称之为AbstractFoo,它可以根据特定类Bar的属性“接受”或“拒绝”该类的实例。因此,我在AbstractFoo基类中添加了以下方法: public abstract boolean acceptsBar(Bar bar); public abstract Optional<BarRejection> getBarRejection(Bar bar); 然而,我随后发现,在某些情况下,我需要知道Bar被拒绝的原因,并且此拒绝消息非常复杂,足以保证使用一
AbstractFoo
,它可以根据特定类Bar
的属性“接受”或“拒绝”该类的实例。因此,我在AbstractFoo
基类中添加了以下方法:
public abstract boolean acceptsBar(Bar bar);
public abstract Optional<BarRejection> getBarRejection(Bar bar);
然而,我随后发现,在某些情况下,我需要知道Bar
被拒绝的原因,并且此拒绝消息非常复杂,足以保证使用一种新类型的对象来表示它:BarRejection
。然后,我将以下方法添加到AbstractFoo
基类中:
public abstract boolean acceptsBar(Bar bar);
public abstract Optional<BarRejection> getBarRejection(Bar bar);
这一切都很好,除了我现在剩下的是我认为的风格问题。在大多数情况下,我不在乎为什么Bar
被拒绝,所以我最终写了如下内容:
@Override
public Optional<BarRejection> getBarRejection(Bar bar) {
return ([acceptance condition]) ? Optional.empty() : BarRejection.default();
}
强制
AbstractFoo
的派生类恰好实现这两个方法中的一个,而未实现的方法将采用其默认行为,这将是非常理想的。显然,这在Java中不可能直接实现,但有没有一种设计模式可以让我完成类似的事情?您可以为不想提供拒绝原因的客户创建第二个抽象基类:
public abstract class AbstractFoo {
public final boolean acceptsBar(Bar bar) {
return !getBarRejection(bar).isPresent();
}
public abstract Optional<BarRejection> getBarRejection(Bar bar);
}
public abstract class AbstractQuickRejectFoo extends AbstractFoo {
@Override
public Optional<BarRejection> getBarRejection(Bar bar) {
return checkAcceptBar(bar) ? Optional.empty() : BarRejection.getDefault();
}
protected abstract boolean checkAcceptBar(Bar bar);
}
公共抽象类AbstractFoo{
公共最终布尔接受条(条形){
return!getBarRejection(bar).isPresent();
}
公共摘要可选getBarRejection(Bar);
}
公共抽象类AbstractQuickRejectFoo扩展了AbstractFoo{
@凌驾
公共可选getBarRejection(条形){
返回checkAcceptBar(bar)?可选。空():BarRejection.getDefault();
}
受保护的抽象布尔checkAcceptBar(Bar);
}
希望提供自定义原因的派生类将直接继承
AbstractFoo
,而希望提供默认原因的类将继承AbstractQuickRejectFoo
。每个类都为它们的子类提供了一个可重写的抽象方法。default
是一个保留关键字。既然您现在有了真实世界的用例,那么在处理拒绝时您能列出三个吗?典型的动作是什么?记录什么?抛出异常?我遇到过类似的场景,其中3个默认方法将它们的实现转发给另一个,我在文档中留下了一条警告,其中一个方法必须被重写。这不是理想的解决方案,但我找不到更好的解决方案。@shmosel在我的理解中,default
特别适用于接口,在这种情况下,它与我在问题中所做的在抽象类中实现方法相同(也许我应该更清楚Foo
)。除了允许重写这两个方法之外,我在接口中实现这两个default
s时看到的问题是它们相互引用,编译器不会警告用户这种行为。在不重写至少一个接口的情况下实现接口将导致堆栈溢出(如果在编译时这样做是合法的话)。我决定冒这个险。不理想,就像我说的。@shmosel是的,你是对的,我重命名了类,但忘记重命名引用。这很有意义!我不希望仅仅为了适应这个单一的构造而使类层次结构进一步复杂化,但我想我直觉地理解,这可能是处理这种情况的唯一真正的“面向对象”的方法。这里的主要问题是有许多可扩展的Foo
子类,它们的特定行为与它们是否应该QuickReject
正交,因此每个子类都需要自己的QuickReject
等价物。我认为目前的制度可能比这样做更好。但是,+1。