位置:首頁 > Java技術 > Java基礎教程 > Java抽象

Java抽象

抽象是指能夠使一個抽象類在麵向對象編程的能力。抽象類是不能被實例化。該類彆的所有其他功能仍然存在,及其字段,方法和構造函數以相同的方式被訪問的。不能創建抽象類的實例。

如果一個類是抽象的,不能被實例化,類冇有多大用處,除非它是子類。這通常是在設計階段的抽象類是怎麼來的。父類包含子類的集合的通用功能,但父類本身是過於抽象而被單獨使用。

抽象類:

使用abstract關鍵字來聲明一個類的抽象。關鍵字出現在類聲明的地方class關鍵字前。

/* File name : 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");
      this.name = name;
      this.address = address;
      this.number = number;
   }
   public double computePay()
   {
     System.out.println("Inside 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類冇有什麼不同。這個類是抽象的現在,但它仍然有三個字段,七種方法,和一個構造函數。

現在,如果想嘗試如下:

/* File name : AbstractDemo.java */
public class AbstractDemo
{
   public static void main(String [] args)
   {
      /* Following is not allowed and would raise error */
      Employee e = new Employee("George W.", "Houston, TX", 43);

      System.out.println("
 Call mailCheck using Employee reference--");
      e.mailCheck();
    }
}

當編譯上麵的類,那麼會得到以下錯誤:

Employee.java:46: Employee is abstract; cannot be instantiated
      Employee e = new Employee("George W.", "Houston, TX", 43);
                   ^
1 error

擴展抽象類:

我們可以以正常的方式擴展Employee類,如下所示:

/* File name : Salary.java */
public class Salary extends Employee
{
   private double salary; //Annual salary
   public Salary(String name, String address, int number, double
      salary)
   {
       super(name, address, number);
       setSalary(salary);
   }
   public void mailCheck()
   {
       System.out.println("Within mailCheck of Salary class ");
       System.out.println("Mailing check to " + getName()
       + " with salary " + salary);
   }
   public double getSalary()
   {
       return salary;
   }
   public void setSalary(double newSalary)
   {
       if(newSalary >= 0.0)
       {
          salary = newSalary;
       }
   }
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }
}

在這裡,我們不能實例化一個新Employee,但如果我們實例化一個新的Salary 對象,Salary 對象將繼承這三個字段,並從員工七種方法。

/* File name : 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("Call mailCheck using Salary reference --");
      s.mailCheck();

      System.out.println("
 Call mailCheck using Employee reference--");
      e.mailCheck();
    }
}

這將產生以下結果:

Constructing an Employee
Constructing an Employee
Call mailCheck using  Salary reference --
Within mailCheck of Salary class
Mailing check to Mohd Mohtashim with salary 3600.0

Call mailCheck using Employee reference--
Within mailCheck of Salary class
Mailing check to John Adams with salary 2400.

抽象方法:

如果你想有一個類包含一個特定的方法,但是希望該方法由子類來決定的實際執行情況,可以在父類中聲明的抽象方法。

abstract關鍵字也可以用來聲明一個方法為抽象。抽象方法由一個方法簽名,但冇有方法體。

抽象方法就冇有定義,其簽名後跟一個分號,而不是花括號,如下所示:

public abstract class Employee
{
   private String name;
   private String address;
   private int number;
   
   public abstract double computePay();
   
   //Remainder of class definition
}

聲明一個方法為抽象有兩種方式:

  • 這個類也必須聲明為抽象的。如果一個類包含一個抽象方法的類必須是抽象的也是如此。

  • 所有子類必須要麼重寫抽象方法或者聲明本身也為抽象。

繼承一個抽象方法的子類必須覆蓋它。如果他們不這樣做,他們必須是抽象的,任何子女必須重寫它。

最後,子類必須實現的抽象方法,否則,將有抽象類,不能被實例化的層次結構。

如果Salary 在擴展Employee類,那麼它是實現computePay() 方法如下要求:

/* File name : Salary.java */
public class Salary extends Employee
{
   private double salary; // Annual salary
  
   public double computePay()
   {
      System.out.println("Computing salary pay for " + getName());
      return salary/52;
   }

   //Remainder of class definition
}