【问题标题】:Force every class of an inheritance chain to override an abstract method强制继承链的每个类重写抽象方法
【发布时间】:2012-05-05 02:56:19
【问题描述】:

假设我有一个继承链,其中每个类都通过添加一个新字段来扩展其超类,并且我希望该链的每个类都覆盖 toString() 方法,如下所示:

public String toString()
{
    return super.toString() + "[newfield=" + newfield + "]";
}

如果我使用抽象基类,那么当继承链的一个类通过实现抽象方法变得具体时,从那时起所有子类也通过继承已经实现的方法变得具体。

在 Java 中是否有办法强制每个类重写(重新实现)抽象方法,即使它已经在继承链中更高层实现?

【问题讨论】:

    标签: java inheritance


    【解决方案1】:

    不,但是您可以让您的类实现接口而不是抽象超类。如果类实现了接口,您可以检查编译时间,这取决于您对这些类执行的操作。

    【讨论】:

      【解决方案2】:

      简短回答:不。

      长答案:您可以编写一个扫描类路径的单元测试(为此使用像reflections 这样的库),加载抽象类的每个子类并使用反射检查方法。但是没有办法在编译时这样做。

      除了 Java, AspectJ 有一个hasMethod() 切入点,它可以为您进行检查,但不幸的是,这只对declare parents 建议有效。也许您可以使用 aspectj 分两步完成:

      • 定义一个接口IllBehaved
      • 定义一个建议,将此接口分配给从您的基类扩展但没有成员的类
      • 然后为所有实现该接口的类型声明一个编译错误

        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 是编译时)。
      • @EliAcherkan 是的,好点。但我想你只有在所有覆盖类上都有注释时才能这样做,对吧?或者用@Inherited 标记的注释可以完成这项工作?
      • 好问题,我承认我还没有完全考虑清楚。我希望用注释标记最顶层的类就足够了,并且 APT 允许您 a) 找到给定类的后代列表;或者 b) 在所有类上调用你的注解处理器(这样你就可以检查当前类的祖先是否有一个特定的注解)。
      • @EliAcherkan 我很确定 a) 和 b) 都不可能。如果您的班级没有注释,则 apt 看不到它
      • 我不知道这一点。所以也许 APT 毕竟不是最好的工具:-)
      猜你喜欢
      • 1970-01-01
      • 2017-11-27
      • 1970-01-01
      • 1970-01-01
      • 2012-08-06
      • 2013-07-01
      • 1970-01-01
      • 2013-11-28
      • 2012-11-17
      相关资源
      最近更新 更多