【问题标题】:Understanding the purpose of Abstract Classes in Java理解 Java 中抽象类的目的
【发布时间】:2012-03-01 03:16:05
【问题描述】:

假设我有两个类,A 和 B。A 类被定义为抽象类,而 B 扩展了这个抽象类,最后我测试了结果,两个类都是同一个包的一部分。

public abstract class A {

    protected abstract void method1(); 

    protected void method2() { 
        System.out.println("This is Class A's method"); 
    } 
}

public class B extends A {

    @Override
    protected void method1() {
        System.out.println("This is B's implementaiton of A's method");
    } 
}  

现在当我测试它们时:

B b = new B();
b.method1();
b.method2();  

我得到了预期的输出:

This is B's implementaiton of A's method
This is Class A's method

问题:

  • @Override关键字的目的是什么,因为如果我省略它,它 仍然工作相同。
  • 如果我不实现抽象方法,我会得到一个编译错误。那么与实现接口有什么区别呢?
  • 另外,我也可以在 B 中实现method2()。然后输出变为B中使用的东西。这不是也覆盖了父类方法吗?那么在Class A中显式定义一个方法为abstract的目的是什么?

【问题讨论】:

标签: java overriding abstract-class


【解决方案1】:

抽象类允许您存储基本级别的实现(继承),同时还生成保证继承的类将自行实现特定功能(接口)的契约...

虽然永远不会有抽象类的实例,但您可以在继承者之间存储共享功能...

我一直认为它们是允许某些方法的基本实现的接口......

【讨论】:

  • +1 用于抽象类作为“与某些方法的基本实现的接口”
  • 你的回答让我清楚地理解了其中的区别。
【解决方案2】:
  1. @Override 不是关键字,它是一个可选的注解,它可以帮助编译器检查您是否确实覆盖了一个方法。如果你说@Override 但没有方法可以覆盖,编译器会告诉你你可能打错了。将method1重命名为method12看看效果。
  2. 接口不能有任何实现,而抽象类可以选择为其某些方法提供实现。此外,接口不能有数据成员。
  3. 将方法定义为抽象意味着派生类必须提供实现。不将其声明为抽象表示派生类只是可以提供自己的实现,但它们不需要。

【讨论】:

  • @911TurboS 如果答案正确,您应该将答案标记为已回答(向下箭头符号下方的按钮)。
【解决方案3】:

当你有多个类实现并且从method2调用method1时,真正的用法就出现了。在这种情况下,执行完method2之后,相应类中的method1就会被执行。

public abstract class A {

    protected abstract void method1(int val); 

    protected void method2() { 
        System.out.println("This is Class A's method");
        //Let us I calculated something here, may be sum of two ints 
        method1(//pass above calculated int);
    } 
}

public class B extends A {

    @Override
    protected void method1(int val) {
        System.out.println("This is B's implementaiton of A's method");
        //Here you may do this class specific manipulation on val.
    } 
}  

就像在 C 类中一样,您可以操作常见的计算一些。

【讨论】:

    【解决方案4】:

    抽象类和接口的主要区别在于接口只定义一个接口,抽象类也可以有一个实现和字段/属性。

    可以将抽象类视为 IS-A 关系(例如,马是动物)。对于接口,它主要是类可以具有的一些特性(例如 INavigable、ISortable)。

    也不能实例化抽象方法(接口也不可以)。

    重写函数是为了表明一个函数有一个基类实现。

    也不能/建议使用类进行多重继承,因此最大。仅使用一个基类并从接口继承其他功能。

    【讨论】:

      【解决方案5】:

      @Override 关键字的目的是什么,因为如果我省略它,它 还是一样。

      易读性。

      如果我没有实现抽象方法,我会得到编译错误。那么什么是 实现接口的区别?

      接口不允许您包含代码。

      另外,我也可以在 B 中实现 method2()。然后输出改变 到 B 中使用的内容。这不是也覆盖了父类吗 方法。那么显式定义方法的目的是什么 A 类的摘要?

      是的,它覆盖了父方法。您通常将方法定义为抽象的,以便将实现留给孩子(必须实现它或者是抽象的)。如果它不是抽象的,你必须实现它。

      【讨论】:

      • 接口确实允许您包含“代码”,它们是客户端如何与实现该接口的对象交互(接口)的声明。它们可以用作参考类型,实习生通过将客户端从任何抽象或具体实现中封装来促进多态性。变量可以在接口中声明,但是默认情况下(和定义)是静态的,因为永远不会有接口的实例。您使用抽象方法来强制执行未知或可能在子实现之间更改的具体实现
      【解决方案6】:

      @Override

      @Override 是在 Java 5 中引入的(并在 Java 6 中进行了一些扩展)。它只是提供信息。它说“我想覆盖父类或接口中已经存在的东西。

      IDE 之类的 Eclipse 可以在没有这样的父方法的情况下向您发出警告(例如,如果您拼错了名称)。在这种情况下,您的方法将不会被调用(因为拼写错误)。

      不过不用太担心。

      抽象类与接口

      抽象类允许您定义基本功能而留下未定义的部分。接口不允许您实现任何东西。除了在每种情况下真正改变的部分之外,您可以对所有内容进行编程。所以当你需要它的时候,你继承并实现缺失的部分。

      覆盖两个方法

      是的。在 Java 中,您可以覆盖所有未在父类中明确声明为 final 的方法。没关系。如果你想让它不可修改,你可以将它声明为 final。例如,如果你想声明一个排序,你可以:

      public abstract class Ordering<X>
      {
      abstract boolean isLower(X a, X b);
      abstract boolean isEquals(X a, X b);
         final boolean isGreater(X a, X b) {
            return !isLower(a, b) && !isEquals(a, b);
         }
      }
      

      当然,重写 isGreater 以另一种更有效的方式实现它可能是有意义的(想象一下比较成本很高)。但是在某些情况下,您想提供基本的已经实现的功能(然后是抽象类比接口更好的时候)或者当您想要强制执行某些情况(然后是 final 关键字显示有用的时候)。

      【讨论】:

      • 非常感谢!无论如何,您将通过查看示例来习惯抽象/接口等等。 Spring 框架就是一个很好的例子。事实上,如果您了解设计模式:抽象类与模板方法非常接近,而接口则与(以及许多其他事物)策略模式相关。模板通过继承扩展,而策略通过组合扩展。再次重申:带有所有模板和组件的 Spring 框架就是一个很好的例子。随着时间的推移你会发现的。
      【解决方案7】:

      What is the purpose of @Override keyword

      是后来的Java加法,是为了弱自控。是注解,即库类,不是关键字。

      So what is the difference to implementing an interface?

      很少。 Iterface 是一个所有方法都是抽象的类。此外,只允许一个类父级,而它可以是多个接口。您也可以将成员放入类中,但不能放入接口中。

      Then what is the purpose of explicitly Defining a method abstract in Class A?

      只有当它没有主体时才应该声明它是抽象的。 JVM 需要知道所有后代都会拥有它。

      【讨论】:

        【解决方案8】:

        这个article 有一些关于你的问题标题的好概念(和例子)。

        抽象类是包含一个或多个抽象方法的类。 抽象方法是一种已声明但不包含实现的方法。 抽象类可能不会被实例化,并且需要子类来提供抽象方法的实现。

        假设您想定义一个具有某些方法的类,但无论您的程序/项目的设计目的是什么,您都希望确保在以下情况下必须实现特定方法(抽象方法抽象类被扩展了。

        基本上,抽象类的目的是定义一个具有以下方法的类:

        • 必须在子类上声明(抽象)
        • 在子类上可选地使用(非抽象)


        附加评论

        • 几年前,我为Android(Java,不是Kotlin)开发了一个应用程序,在使用许多库的过程中,我经历了用抽象类扩展我的类的行为,并且由于这种类的行为, Android Studio 自动将所有抽象方法添加到我的代码中,它们是我正在扩展的抽象类的一部分。

        【讨论】:

          猜你喜欢
          • 2020-04-03
          • 1970-01-01
          • 2011-05-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-11
          • 1970-01-01
          相关资源
          最近更新 更多