Java 抽象怎么用?如何在代码中实现抽象类和接口?

文章导读
Previous Quiz Next 根据词典定义,abstraction(抽象)是指处理思想而非事件的特性。例如,在电子邮件的情况下,用户无需了解发送电子邮件后发生的复杂细节,如电子邮件服务器使用的协议等,这些都被隐藏起来了。因此,要发送电子邮件,您只需输入内容、指定收件
📋 目录
  1. A Java 抽象
  2. B Java 抽象类
  3. C 继承 Java 抽象类
  4. D Java 抽象方法
A A

Java - 抽象



Previous
Quiz
Next

根据词典定义,abstraction(抽象)是指处理思想而非事件的特性。例如,在电子邮件的情况下,用户无需了解发送电子邮件后发生的复杂细节,如电子邮件服务器使用的协议等,这些都被隐藏起来了。因此,要发送电子邮件,您只需输入内容、指定收件人地址,然后点击发送即可。

Java 抽象

抽象是将实现细节隐藏起来只向用户提供功能的过程。换言之,用户只需知道对象的功能是什么,而无需了解它是如何实现的。在 Java 编程中,抽象通过 Abstract classes(抽象类)和 interfaces(接口)来实现。

Java 抽象类

在 Java 中,如果一个类的声明中包含 abstract 关键字,则该类被称为抽象类。

  • Java 抽象类可以包含或不包含 abstract methods,即没有方法体的方法( public void get(); )

  • 但是,如果一个类至少有一个 abstract method,则该类 必须 被声明为 abstract。

  • 如果一个类被声明为 abstract,它不能被实例化。

  • 要使用抽象类,必须从另一个类继承它,并为其中的 abstract methods 提供实现。

  • 如果继承了一个抽象类,必须为其中所有的 abstract methods 提供实现。

示例:Java 抽象类

本节提供一个 Java 抽象类的示例。要在 Java 中创建抽象类,只需在类声明中 class 关键字前使用 abstract 关键字。

/* 文件名 : Employee.java */
/* 文件名:Employee.java */
public abstract class Employee {
   private String name;
   private String address;
   private int number;

   public Employee(String name, String address, int number) {
      System.out.println("Constructing an Employee");
      /* 构造一个 Employee */
      this.name = name;
      this.address = address;
      this.number = number;
   }
   
   public double computePay() {
     System.out.println("Inside Employee computePay");
     /* 在 Employee computePay 内 */
     return 0.0;
   }
   
   public void mailCheck() {
      System.out.println("Mailing a check to " + this.name + " " + this.address);
      /* 向此人寄送支票: */
   }

   public String toString() {
      return name + " " + address + " " + number;
   }

   public String getName() {
      return name;
   }
 
   public String getAddress() {
      return address;
   }
   
   public void setAddress(String newAddress) {
      address = newAddress;
   }
 
   public int getNumber() {
      return number;
   }
}

您可以观察到,除了 abstract methods 外,Employee 类与 Java 中的普通类相同。该类现在是 abstract 的,但它仍然有三个字段、七个方法和一个构造函数。

现在您可以尝试以下方式实例化 Employee 类 −

/* 文件名 : AbstractDemo.java */
/* 文件名:AbstractDemo.java */
public class AbstractDemo {

   public static void main(String [] args) {
      /* 以下操作不允许,会引发错误 */
      Employee e = new Employee("George W.", "Houston, TX", 43);
      System.out.println("\n Call mailCheck using Employee reference--");
      /* 使用 Employee 引用调用 mailCheck -- */
      e.mailCheck();
   }
}

abstract class Employee {
   private String name;
   private String address;
   private int number;

   public Employee(String name, String address, int number) {
      System.out.println("Constructing an Employee");
      /* 构造一个 Employee */
      this.name = name;
      this.address = address;
      this.number = number;
   }
   
   public double computePay() {
     System.out.println("Inside Employee computePay");
     /* 在 Employee computePay 内 */
     return 0.0;
   }
   
   public void mailCheck() {
      System.out.println("Mailing a check to " + this.name + " " + this.address);
      /* 向此人寄送支票: */
   }

   public String toString() {
      return name + " " + address + " " + number;
   }

   public String getName() {
      return name;
   }
 
   public String getAddress() {
      return address;
   }
   
   public void setAddress(String newAddress) {
      address = newAddress;
   }
 
   public int getNumber() {
      return number;
   }
}

当您编译上述类时,会出现以下错误 −

Employee.java:46: Employee is abstract; cannot be instantiated
      /* Employee 是抽象的;不能被实例化 */
      Employee e = new Employee("George W.", "Houston, TX", 43);
                   ^
1 error

继承 Java 抽象类

我们可以像继承具体类一样,以以下方式继承 Employee 类的属性 −

示例:在 Java 中继承抽象类

/* 文件名 : Salary.java */
public class Salary extends Employee {
   private double salary;   // 年薪
   
   public Salary(String name, String address, int number, double salary) {
      super(name, address, number);
      setSalary(salary);
   }
   
   public void mailCheck() {
      System.out.println("在 Salary 类的 mailCheck 中 ");
      System.out.println("邮寄支票给 " + getName() + ",薪资 " + salary);
   }
 
   public double getSalary() {
      return salary;
   }
   
   public void setSalary(double newSalary) {
      if(newSalary >= 0.0) {
         salary = newSalary;
      }
   }
   
   public double computePay() {
      System.out.println("为 " + getName() + " 计算薪资");
      return salary/52;
   }
}

在这里,你不能实例化 Employee 类,但你可以实例化 Salary 类,并通过这个实例访问 Employee 类的所有三个字段和七个方法,如下所示。

/* 文件名 : AbstractDemo.java */
public class AbstractDemo {

   public static void main(String [] args) {
      Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
      Employee e = new Salary("John Adams", "Boston, MA", 2, 2400.00);
      System.out.println("使用 Salary 引用调用 mailCheck --");
      s.mailCheck();
      System.out.println("\n 使用 Employee 引用调用 mailCheck--");
      e.mailCheck();
   }
}
abstract class Employee {
   private String name;
   private String address;
   private int number;

   public Employee(String name, String address, int number) {
      System.out.println("构造 Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   
   public double computePay() {
     System.out.println("在 Employee 的 computePay 中");
     return 0.0;
   }
   
   public void mailCheck() {
      System.out.println("邮寄支票给 " + this.name + " " + this.address);
   }

   public String toString() {
      return name + " " + address + " " + number;
   }

   public String getName() {
      return name;
   }
 
   public String getAddress() {
      return address;
   }
   
   public void setAddress(String newAddress) {
      address = newAddress;
   }
 
   public int getNumber() {
      return number;
   }
}
class Salary extends Employee {
   private double salary;   // 年薪
   
   public Salary(String name, String address, int number, double salary) {
      super(name, address, number);
      setSalary(salary);
   }
   
   public void mailCheck() {
      System.out.println("在 Salary 类的 mailCheck 中 ");
      System.out.println("邮寄支票给 " + getName() + ",薪资 " + salary);
   }
 
   public double getSalary() {
      return salary;
   }
   
   public void setSalary(double newSalary) {
      if(newSalary >= 0.0) {
         salary = newSalary;
      }
   }
   
   public double computePay() {
      System.out.println("为 " + getName() + " 计算薪资");
      return salary/52;
   }
}

输出

构造 Employee
构造 Employee
使用 Salary 引用调用 mailCheck --
在 Salary 类的 mailCheck 中 
邮寄支票给 Mohd Mohtashim,薪资 3600.0

 使用 Employee 引用调用 mailCheck--
在 Salary 类的 mailCheck 中 
邮寄支票给 John Adams,薪资 2400.0

Java 抽象方法

如果您希望一个 class 包含特定 method,但希望该 method 的实际实现由子类决定,您可以在父类中将该 method 声明为 abstract。

  • abstract 关键字用于将 method 声明为 abstract。

  • 您必须在 method 声明中 method 名称之前放置 abstract 关键字。

  • 抽象 method 包含 method 签名,但没有 method 体。

  • 抽象 method 在末尾使用分号 (;) 而不是大括号。

示例 1:Java 中的抽象方法实现

以下是抽象方法的示例。

public abstract class Employee {
   private String name;
   private String address;
   private int number;
   
   public abstract double computePay();
   // 类的其余定义
}

将 method 声明为 abstract 有两个后果 −

  • 包含它的 class 必须被声明为 abstract。

  • 继承当前 class 的任何 class 必须要么重写抽象 method,要么将自身声明为 abstract。

注意 − 最终,后代 class 必须实现抽象 method;否则,您将得到一个无法实例化的抽象 class 层次结构。

假设 Salary class 继承 Employee class,那么它应该像下面这样实现 computePay() method −

/* 文件名 : Salary.java */
public class Salary extends Employee {
   private double salary;   // 年薪
  
   public double computePay() {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
   // 类的其余定义
}

示例 2:Java 中的抽象方法实现

以下示例展示了抽象方法的概念。

/* 文件名 : AbstractDemo.java */
public class AbstractDemo {
   public static void main(String [] args) {
      Salary s = new Salary("Mohd Mohtashim", "Ambehta, UP", 3, 3600.00);
      System.out.println("salary: " + s.computePay());
   }
}
abstract class Employee {
   private String name;
   private String address;
   private int number;

   public Employee(String name, String address, int number) {
      System.out.println("Constructing an Employee");
      this.name = name;
      this.address = address;
      this.number = number;
   }

   public abstract double computePay();
      // 类的其余定义

   public String getName() {
      return name;
   }

   public void setName(String name) {
      this.name = name;
   }

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }

   public int getNumber() {
      return number;
   }

   public void setNumber(int number) {
      this.number = number;
   }
}
class Salary extends Employee {
   private double salary;   // 年薪

   public Salary(String name, String address, int number, double salary) {
      super(name, address, number);
      this.salary = salary;
   }

   public double computePay() {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
   // 类的其余定义
}

输出

Constructing an Employee
Computing salary pay for Mohd Mohtashim
salary: 69.23076923076923