【问题标题】:How to force implementation of a method in subclass without using abstract?如何在不使用抽象的情况下强制实现子类中的方法?
【发布时间】:2013-08-20 09:18:29
【问题描述】:

我想强制子类实现我母类的实现方法。 我看这个Java - Force implementation of an implemented method,但我无法将我的母类转换为抽象类。

public class myMotherClass { 

   myMethod {

      ...some code ..

   }

}

public class myClass extends myMotherClass {

   myMethod {

      ... other code ...
   }

}

所以,在这个例子中,我想强制 myClass 实现 myMethod。

对不起我的英语......

【问题讨论】:

  • 简而言之:你不能不把它抽象化
  • @stonedsquirrel 接口呢?
  • 如果类没有实现该方法,使用注释或抛出异常是不可能的?
  • @KevinBowersox 当然有办法通过改变设计来创建这样的行为。我所说的只是强制从超类中重写非抽象方法是不可能的。接口也无济于事,因为超类也会实现它。这样子类就不会再被强制实现该方法了。

标签: java class methods abstract implements


【解决方案1】:

大多数人忽略的一件事是以下实现(尽管我在评论中看到提到它):

public class MyMotherClass { 

    public void myMethod() {
      throw new RuntimeException("Method not overwritten");
    }    

}

在大多数情况下,这应该足够了,因为您应该进行某种形式的验收测试(即使它只是手动测试继承类)。从理论上讲,您仍然在引入一种可能性,即没有人会意识到该方法在生产之前还没有被过度使用。

【讨论】:

  • 这也只在你不需要父类的实现时才有效。
【解决方案2】:

您不能强制子类覆盖方法。您只能通过使其抽象来强制它实现方法。

所以如果你不能使 myMotherClass 抽象,你只能引入另一个超类来扩展 myMotherClass 并委托给必须实现的方法:

public abstract class EnforceImplementation extends myMotherClass {

        public final void myMethod(){
             implementMyMethod();
        }

        public abstract void implementMyMethod();
}

编辑

我在hemcrest api 中找到了另一种解决问题的有趣方法,例如由 mockito 使用。

public interface Matcher<T> extends SelfDescribing {

    /**
     * Evaluates the matcher for argument <var>item</var>.
     * <p/>
     * This method matches against Object, instead of the generic type T. This is
     * because the caller of the Matcher does not know at runtime what the type is
     * (because of type erasure with Java generics). It is down to the implementations
     * to check the correct type. 
     *
     * @param item the object against which the matcher is evaluated.
     * @return <code>true</code> if <var>item</var> matches, otherwise <code>false</code>.
     *
     * @see BaseMatcher
     */
    boolean matches(Object item);

    /**
     * This method simply acts a friendly reminder not to implement Matcher directly and
     * instead extend BaseMatcher. It's easy to ignore JavaDoc, but a bit harder to ignore
     * compile errors .
     *
     * @see Matcher for reasons why.
     * @see BaseMatcher
     */
    void _dont_implement_Matcher___instead_extend_BaseMatcher_();
}

接口指定了一个方法_dont_implement_Matcher___instead_extend_BaseMatcher_。当然它并不妨碍其他人实现Matcher 接口,但它引导开发者朝着正确的方向前进。

BaseMatcher 类将_dont_implement_Matcher___instead_extend_BaseMatcher_ 方法实现为final

public final void _dont_implement_Matcher___instead_extend_BaseMatcher_() {
    // See Matcher interface for an explanation of this method.
}

最后我认为这是一个设计问题,因为BaseMatcher 显然实现了每个Matcher 都应该实现的逻辑。因此,最好将Matcher 设为抽象类并使用模板方法。

但我猜他们这样做是因为这是字节码兼容性和新功能之间的最佳折衷。

【讨论】:

    【解决方案3】:

    您可以重新设计您的层次结构,以便您的具体类只是树的叶子。

    代替

    myClass extends myMotherClass
    

    考虑

    myClass extends myMotherAbstractClass
    myMotherClass extends myMotherAbstractClass 
    

    这样,两个实例化的类都继承了 Abstract 类。在这种情况下,myMotherClass 可能会非常薄,只是myMethod 的实现。

    【讨论】:

      【解决方案4】:

      如果你真的想强制实现方法使用应该使用interface

      public interface MyInterface{
      
         void myMethod();
      }
      

      现在如果有人想从这个接口实现MyClass implements MyInterface,你必须实现myMethod();

      public MyClass implements MyInterface{
      
        public void myMethod{
           // do something
         }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2021-04-20
        • 2013-08-02
        • 2012-11-14
        • 2023-04-06
        • 1970-01-01
        • 1970-01-01
        • 2022-07-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多