Java抽象クラス



オブジェクト指向の概念では、すべてのオブジェクトはクラスによって記述されますが、逆に、クラスに Concrete オブジェクトを記述するのに十分な情報が含まれていない場合、そのようなクラスは抽象クラスになります。

抽象クラスはオブジェクトをインスタンス化できないことを除いて、クラスの他の関数は通常のクラスと同じ方法でアクセスできます。

抽象クラスはオブジェクトをインスタンス化できないため、抽象クラスは使用する前に継承する必要があります。このため、通常は設計段階で抽象クラスを設計するかどうかを決定します。

親クラスには子クラスのコレクションに共通のメソッドが含まれていますが、親クラス自体が抽象クラスであるため、これらのメソッドは使用できません。


抽象クラス

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");
      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;
   }
}

このクラスは抽象クラスですが、3 つのメンバー変数、7 つのメンバー メソッド、および 1 つのコンストラクターがあることに注意してください。 ここで、次の例を試してみると:

/* 文件名 : 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--");
      e.mailCheck();
    }
}

AbstractDemo クラスをコンパイルしようとすると、次のエラーが生成されます:

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

抽象クラスの継承

通常のメソッドを通じて Employee クラスを継承できます:

/* 文件名 : 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クラスのオブジェクトをインスタンス化すると、そのオブジェクトはEmployeeクラスから3つのメンバ変数と7つのメンバメソッドを継承することになります。

/* 文件名 : 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("\n 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();
   
   //其余代码
}

抽象メソッドを宣言すると、次の 2 つの結果が生じます:

  • クラスに抽象メソッドが含まれる場合、クラスは抽象クラスである必要があります。

  • サブクラスは親クラスの抽象メソッドをオーバーライドするか、それ自体を抽象クラスとして宣言する必要があります。

抽象メソッドを継承するサブクラスは、このメソッドをオーバーライドする必要があります。それ以外の場合は、サブクラスも抽象として宣言する必要があります。最終的には、サブクラスは抽象メソッドを実装する必要があります。そうしないと、最初の親クラスも最後のサブクラスもオブジェクトのインスタンス化に使用できません。

Salary クラスが Employee クラスを継承する場合、computePay() メソッドを実装する必要があります:

/* 文件名 : 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;
   }

   //其余代码
}