理解 Java 中抽象类的用途

IT小君   2021-10-27T02:35:44

假设我有两个类,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关键字的目的是什么,因为如果我省略它,它仍然有效。
  • 如果我不实现抽象方法,就会出现编译错误。那么和实现接口有什么区别呢?
  • 另外,我也可以method2()在 B 中实现然后输出变成了 B 中使用的内容。这不是也覆盖了父类方法吗?那么在A类中显式定义一个方法为抽象的目的是什么
点击广告,支持我们为你提供更好的服务
评论(8)
IT小君
  1. @Override不是关键字,它是一个可选的注释,可帮助编译器检查您是否确实覆盖了一个方法。如果你说@Override但没有方法可以覆盖,编译器会告诉你你可能打错了。重命名method1method12查看效果。
  2. 接口不能有任何实现,而抽象类可以选择为其某些方法提供实现。此外,接口不能有数据成员。
  3. 将方法定义为抽象意味着派生类必须提供实现。不将其声明为抽象表示派生类可以简单地提供它们自己的实现,但它们不需要。
2021-10-27T02:35:44   回复
IT小君

@覆盖

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

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

但不要太担心。

抽象类 vs 接口

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

覆盖两个方法

是的。在 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 关键字显示有用的时候)。

2021-10-27T02:35:44   回复
IT小君

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

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

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

2021-10-27T02:35:45   回复
IT小君

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

抽象类可以看作是一种 IS-A 关系(例如,马是一种动物)。对于接口,它主要是类可以具有的某些功能(例如 INavigable、ISortable)。

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

覆盖函数是为了表明一个函数有一个基类实现。

此外,多继承是不可能/建议与类,因此最大。仅使用一个基类并从接口继承其他功能。

2021-10-27T02:35:45   回复
IT小君

@Override 关键字的目的是什么,因为如果我省略它,它仍然有效。

易读性。

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

接口不允许您包含代码。

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

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

2021-10-27T02:35:45   回复
IT小君

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 需要知道所有后代都会拥有它。

2021-10-27T02:35:45   回复
IT小君

当您实现多个类并且从 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 类中一样,您可以操作常见的计算一些。

2021-10-27T02:35:46   回复
IT小君

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

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

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

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

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


附加评论

  • 几年前,我为Android(Java,不是Kotlin)开发了一个应用程序,在使用很多库的过程中,我经历了用抽象类扩展我的类的行为,并且由于这种类型的类的行为,Android Studio自动添加到我的代码中,所有抽象方法都是我正在扩展抽象类的一部分
2021-10-27T02:35:46   回复