Java 有没有一种方法可以生成一个非抽象但必须重写的方法?

Java 有没有一种方法可以生成一个非抽象但必须重写的方法?,java,inheritance,overriding,abstract-class,abstract-methods,Java,Inheritance,Overriding,Abstract Class,Abstract Methods,有没有办法强迫子类重写超类的非抽象方法 我需要能够创建父类的实例,但是如果一个类扩展了这个类,它必须给出它自己的一些方法的定义。不,这就是抽象方法的全部要点。您的用例是什么?也许我们可以根据潜在的需要来考虑它。据我所知,没有直接的编译器强制执行的方法来实现这一点 您可以通过不使父类可实例化来解决此问题,而是提供一个工厂方法来创建具有默认实现的某些(可能的私有)子类的实例: public abstract class Base { public static Base create() {

有没有办法强迫子类重写超类的非抽象方法


我需要能够创建父类的实例,但是如果一个类扩展了这个类,它必须给出它自己的一些方法的定义。

不,这就是抽象方法的全部要点。您的用例是什么?也许我们可以根据潜在的需要来考虑它。

据我所知,没有直接的编译器强制执行的方法来实现这一点

您可以通过不使父类可实例化来解决此问题,而是提供一个工厂方法来创建具有默认实现的某些(可能的私有)子类的实例:

public abstract class Base {
  public static Base create() {
    return new DefaultBase();
  }

  public abstract void frobnicate();

  static class DefaultBase extends Base {
    public void frobnicate() {
      // default frobnication implementation
    }
  }
}

现在不能编写
newbase()
,但可以执行
Base.create()
来获得默认实现。

考虑使用此方法创建接口。类的后代必须实现它。

答案是否定的。您可以使用模板设计模式重新设计。这可能对你有帮助


或者,您可以让您的子类实现一个接口。接口可能由超类实现,也可能不由超类实现。

如何:在方法的默认实现中,使用反射获取对象的确切类。如果类与基类不完全匹配,则抛出RuntimeException或等效项

public class Parent {

    public void defaultImpl(){
        if(this.getClass() != Parent.class){
            throw new RuntimeException();
        }
    }

}

始终可以使基类具有引发异常的方法

从技术上讲,基类已经定义了该方法,但是如果不重写该方法,它将不可用。在这种情况下,我更喜欢运行时异常,因为它们不需要显式的throws语句。下面是一个例子

public class Parent {

  public void doStuff() {
    throw new RuntimeException("doStuff() must be overridden");
  }

}

public class Child extends Parent {

  @Override
  public void doStuff() {
    ... all is well here ...
  }

}
缺点是这不会阻止创建
Base
对象;但是,任何试图使用其中一个“必须被重写”方法的人很快就会发现,他们应该已经重写了该类

      public Interface audible{
         public void makeSound();

      }

      public class pussyCat implements audible{
          // now you must implement the body of makeSound method here
          public void makeSound(){
            System.out.println("meowwww !!!"); 
          }

          public static void main(String args[]){
           PussyCat aCat=new PussyCat();
           aCat.makeSound(); 
        }
      }

虽然此解决方案很好地满足了请求的描述,但您的应用程序可能会因为不需要这样的解决方案而受益。最好通过编译器检查来避免运行时崩溃,这是abstract关键字提供的功能。

好的,让我们这样来学习。我遵守java风格的指导原则,并使用java语法。因此假设多继承和C++模板不可用。 不一定要使父类方法抽象, 在OOP中使用多态性的概念。您可以通过两种或更多不同的方式使用相同的方法。 这称为方法重写

让我们举个例子

    public class Animal{
       public void makeSound(){
          System.out.println("Animal doesn't know how to make sound");
       }

    }

    public class PussyCat extends Animal{
        public void makeSound(){

           System.out.println("meowwww !!!");
        }

        public static void main(String args[]){
           PussyCat aCat=new PussyCat();
           aCat.makeSound(); 
        }
    }
这将在屏幕上打印“喵喵!!!”

但这并不意味着必须在子类中重写makeSound方法

如果需要强制子类重写这些方法,那么最好通过该类实现一个接口

      public Interface audible{
         public void makeSound();

      }

      public class pussyCat implements audible{
          // now you must implement the body of makeSound method here
          public void makeSound(){
            System.out.println("meowwww !!!"); 
          }

          public static void main(String args[]){
           PussyCat aCat=new PussyCat();
           aCat.makeSound(); 
        }
      }

这也会在屏幕上打印“meowwww!!!”

我会镜像其他答案,并说没有编译器强制的方法来强制派生类重写非抽象方法。使方法抽象化的关键是定义具有此签名的方法必须存在,但不能在基础级别指定,因此必须在派生级别指定。如果在基级有一个方法的工作的、非平凡的实现(比如它不是空的,并且不只是抛出异常或显示消息),那么这对于从派生类的使用者成功调用该方法来说并不是绝对必要的。因此,编译器不必强制重写可以在基本或派生级别上成功运行的方法

在希望派生类重写工作实现的情况下,很明显,基本实现没有满足派生类使用者的需求;基类要么没有足够的实现,要么实现错误。在这些情况下,您必须相信从您的类派生的程序员将知道他在做什么,因此知道需要重写该方法,因为在使用新对象的上下文中,该方法无法生成正确的答案

我能想到你能做的一件事。它需要一个抽象的基础,带有一个密封的(Javaheads的最终版本)“default”实现。这样,就可以像使用“基类”一样随时使用该方法的基本实现,但是为了为新场景定义不同的类,您必须返回到抽象类,并因此被迫重新实现该方法。此方法可能是类中唯一的抽象对象,因此仍然允许您使用其他方法的基本实现:

public abstract class BaseClass
{
   public abstract void MethodYouMustAlwaysOverride();

   public virtual void MethodWithBasicImplementation() { ... }
}

public final class DefaultClass:BaseClass
{
   public override void MethodYouMustAlwaysOverride() { ... }

   //the base implementation of MethodWithBasicImplementation 
   //doesn't have to be overridden
}

...

public class DerivedClass:BaseClass
{
   //Because DefaultClass is final, we must go back to BaseClass,
   //which means we must reimplement the abstract method
   public override void MethodYouMustAlwaysOverride() { ... }

   //again, we can still use MethodWithBasicImplementation, 
   //or we can extend/override it
   public override void MethodWithBasicImplementation() { ... }
}
然而,这有两个缺点。首先,由于您不能通过继承访问DefaultClass的实现,因此无法扩展DefaultClass的实现,这意味着要实现DefaultClass的功能,再加上一些其他功能,您必须从DefaultClass重写代码,这违反了DRY。其次,这只适用于一个继承级别,因为如果允许从DerivedClass继承,则无法强制重写。

也许这有助于:

class SuperClass {

    void doStuff(){

        if(!this.getClass().equals(SuperClass.class)){

            throw new RuntimeException("Child class must implement doStuff Method");
        }else{
            //ok
            //default implementation
        }
    }
}

class Child extends SuperClass{

    @Override
    void doStuff() {
        //ok
    }
}

class Child2 extends SuperClass{

}


 new SuperClass().doStuff(); //ok
 new Child().doStuff();         //ok
 new Child2().doStuff();        //error
这是不可能的原因! 当重写方法时,派生类可以简单地调用基类的实现


那么强制类重写您的方法有什么意义呢?我认为没有任何好处。

正如其他人所指出的,你不能直接这样做

但一种方法是使用策略模式,如下所示:

public class Base {
    private final Strategy impl;

    // Public factory method uses DefaultStrategy
    // You could also use a public constructor here, but then subclasses would
    // be able to use that public constructor instead of the protected one
    public static Base newInstance() {
        return new Base(new DefaultStrategy());
    }

    // Subclasses must provide a Strategy implementation
    protected Base(Strategy impl) {
        this.impl = impl;
    }

    // Method is final: subclasses can "override" by providing a different
    // implementation of the Strategy interface
    public final void foo() {
        impl.foo();
    }

    // A subclass must provide an object that implements this interface
    public interface Strategy {
        void foo();
    }

    // This implementation is private, so subclasses cannot access it
    // It could also be made protected if you prefer
    private static DefaultStrategy implements Strategy {
        @Override
        public void foo() {
            // Default foo() implementation goes here
        }
    }
}

我认为最简单的方法是创建一个从基类继承的抽象类:


public class Base {
    public void foo() {
        // original method
    }
}

abstract class BaseToInheritFrom extends Base {
    @Override
    public abstract void foo();
}

class RealBaseImpl extends BaseToInheritFrom {
    @Override
    public void foo() {
        // real impl
    }
}

可能不建议这样做,但您可以在methode实现中抛出一个exeption(类似methodEmustBeOverridedExp)。
当然,这是运行时强制操作,但可能比nuting更好。

这有什么帮助?如果基类需要是即时的