强制每个继承链中的类重写抽象方法

3
假设我有一个继承链,每个类通过添加新字段扩展其父类,并且我希望该链中的每个类都像这样覆盖toString()方法:
public String toString()
{
    return super.toString() + "[newfield=" + newfield + "]";
}

如果我使用抽象基类,那么当一个继承链的类通过实现抽象方法变为具体类时,从该点开始的所有子类都继承已经实现的方法而成为具体类。

在Java中是否有一种方法可以强制每个类覆盖(重新实现)抽象方法,即使它已经在继承链中更高层次上被实现了?

2个回答

3

简短回答:不行。

详细回答:你可以编写一个单元测试来扫描类路径(使用像reflections这样的库),加载抽象类的每个子类并使用反射检查方法。但无法在编译时完成。

除了Java之外,AspectJ具有hasMethod()切入点,可以为您执行检查,但不幸的是,这仅适用于declare parents建议。也许您可以使用aspectj分两步完成它:

  • define an interface IllBehaved.
  • define an advice that assigns this interface to classes that extend from your base class but don't have the member
  • then declare a compile error for all types that implement this interface

    pointcut isSubTypeOfYourClass(): within(com.your.BaseClass+);
    pointcut overridesMethod(): hasmethod(public void yourMethodName(..));
    declare parents: isSubTypeOfYourClass() && !overridesMethod()
                     implements com.yourcompany.IllBehaved;
    declare error: isSubTypeOfYourClass() && within(com.yourcompany.IllBehaved+):
                     "Implementation class must override <Foo> method";
    

我没有测试过这个,但如果您打开-XhasMember选项,它应该可以工作。 并且当您使用标准工具如Maven、Ant、Eclipse等时,将aspectj集成到您的构建中非常容易。


你可以使用注解和自定义注解处理器(如果你认为APT是编译时)在编译时完成它。 - Eli Acherkan
@EliAcherkan 真的,说得好。但我猜只有在所有重写类上有注释的情况下才能这样做,对吧?或者可能使用带有 @Inherited 标记的注释也可以完成工作? - Sean Patrick Floyd
好问题,我承认我还没有完全想清楚。我希望只需使用注释标记顶层类,然后APT允许您:a)查找给定类的所有子类列表;或b)在所有类上调用您的注释处理器(以便您可以检查当前类的祖先是否具有特定注释)。 - Eli Acherkan
@EliAcherkan 我很确定 a) 和 b) 都不可能。如果你的类没有注释,apt 就看不到它。 - Sean Patrick Floyd
我之前不知道这个。也许APT并不是最好的工具 :-) - Eli Acherkan

2
不,但你可以让你的类实现一个接口而不是抽象超类。你可能可以在编译时检查该类是否实现了接口,这取决于你对这些类做什么。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接