我不太明白为什么你不想使用抽象修饰符——它是用于强制子类实现的,只需要在某些方法而非全部方法中使用。或者你是否在考虑C++风格的“纯虚拟”类?
但许多Java开发人员不知道的另一件事是,也可以覆盖非抽象方法并将它们声明为抽象方法,例如:
public abstract String toString(); // force re-definition
这样即使java.lang.Object
已经定义了一个实现,你也可以强制子类再次定义它。
忽略抽象方法,Java 中没有这样的功能。也许可以创建一个编译时注释来强制执行该行为(我并不确定),但仅此而已。
真正的难点是“覆盖超类中具有必须经过某些逻辑运行的方法”。如果你覆盖了一个方法,除非你显式地调用它,否则超类的方法不会被调用。
在这些情况下,我倾向于做如下处理:
abstract public class Worker implements Runnable {
@Override
public final void run() {
beforeWork();
doWork();
afterWork();
}
protected void beforeWork() { }
protected void afterWork() { }
abstract protected void doWork();
}
强制规定接口方法的特定逻辑结构。例如,您可以使用它来计算调用次数,而无需担心用户是否调用super.run()
等。
如果不能声明一个抽象基类,那么你总是可以抛出UnsupportedOperationException。
class BaseClass {
void mustOverride() {
throw new UnsupportedOperationException("Must implement");
}
}
我不确定你在 .NET 中考虑的是哪个属性。
在 VB 中,你可以对一个方法应用 MustOverride
修饰符,但这只相当于在 Java 中将该方法声明为抽象的。你不需要属性/注释,因为这个概念已经内置到语言中。这不仅仅是应用元数据 - 还有一个关键的区别,即抽象方法本身不包含任何实现。
如果你确实认为有这样的属性,请说明你指的是哪一个?
谷歌 I/O 2015 上宣布,Android 推出了新的注解:@callSuper。
更多细节请查看: http://tools.android.com/tech-docs/support-annotations
public interface SomeLogic {
void execute();
}
public class BaseClass {
//...private stuff and the logging framework of your preference...
private static final SomeLogic MUST_OVERRIDE = new SomeLogic() {
public void execute() {
//do some default naive stuff
}
};
protected SomeLogic getLogic() { return MUST_OVERRIDE; }
//the method that probably would be marked as MustOverride if the option existed in the language, maybe with another name as this exists in VB but with the same objective as the abstract keyword in Java
public void executeLogic() {
getLogic().execute();
}
public BaseClass() {
if (getLogic() == MUST_OVERRIDE) {
log.warn("Using default logic for the important SomeLogic.execute method, but it is not intended for production. Please override the getLogic to return a proper implementation ASAP");
}
}
}
public GoodSpecialization extends BaseClass {
public SomeLogic getLogic() {
//returns a proper implementation to do whatever was specified for the execute method
}
//do some other specialized stuff...
}
public BadSpecialization extends BaseClass {
//do lots of specialized stuff but doesn't override getLogic...
}
根据要求,有些事情可能会有所不同,尤其是对于具有lambda表达式的语言来说,显然更简单,但基本思想是相同的。
如果没有内置的东西,总有一种方法来模拟它,在这个例子中,你将在日志文件中得到一个运行时警告,使用自制的类似模式的解决方案,只有你的需求应该指出是否足够或需要更多的核心字节码操作、IDE插件开发或任何必要的巫术。
我一直在思考这个问题。
虽然我不知道有什么方法可以通过编译错误来要求它,但您可以尝试编写自定义PMD规则,如果您忘记覆盖,则会引发红旗。
已经有很多PMD规则可以做一些事情,例如提醒您实现HhashCode(如果选择覆盖equals)。也许可以像那样做些事情。
我以前从未做过这件事,所以我不是写教程的人,但一个好的起点是这个链接http://techtraits.com/programming/2011/11/05/custom-pmd-rules-using-xpath/。在这个例子中,他基本上创建了一个小警告,如果您决定在导入包中使用通配符,则会出现警告。将其用作探索PMD如何分析源代码、访问层次结构的每个成员并确定您忘记实现特定方法的起点。
注解也是一种可能性,但您必须自己找出实现类路径导航的方法。我相信PMD已经处理了这个问题。此外,PMD与IDE有非常好的集成。 https://pmd.github.io/