Javaプログラミングで、メソッドの実装を義務付けて、メソッドを再利用する方法

Javaプログラミングで

  • クラスのメソッドの実装を義務付けたい。
  • そして、クラスのメソッドを再利用したい。

こういう場合、どうしたら良いですか?

Javaプログラミングで抽象クラスを使うと、以下の二つの事を同時に実現できます。

  1. クラスのメソッドの実装を義務付け。
  2. クラスのメソッドを再利用。

抽象クラスを継承するクラスを、作成してください。
そうすると、上記の「メソッドの実装の義務付け」と「メソッドの再利用」を実現できます。

Javaプログラミングで、メソッドの実装を義務付けて、メソッドを再利用する方法

抽象クラスは、「メソッドの宣言」と「メソッドの実装」を持つクラスです。

抽象クラスは、抽象クラスを継承する(再利用する)クラスに対して、

「メソッド宣言」の実装を義務付けつつ、
抽象クラスがすでに持っているメソッドを再利用できるクラスと言えます。

実際に、この抽象クラスを継承することによって、メソッドを再利用できます。

Javaプログラミングのクラス
Javaプログラミングのクラス・イメージ画像

抽象クラスAbstractOpenActionの例

以下、抽象クラスの例を書きます。
プログラムの詳細を理解する必要は、ありません。

public abstract class AbstractOpenAction extends Action {

    //あるファイルを開くメソッドの宣言
    public abstract ActionForward open(ActionMapping mapping, OpenForm form,
    HttpServletRequest request, HttpServletResponse response);

    public ActionForward execute(ActionMapping mapping, ActionForm form,
    HttpServletRequest request, HttpServletResponse response){

        中略

        //あるファイルを開くメソッドを、呼び出します。
        this.open(mapping, openForm, request, response);

        中略

    }

    中略

}

このAbstractOpenAction抽象クラスの「メソッドの宣言」は、open()メソッドです。

抽象クラスを継承するクラスにおいて、open()メソッドは、プログラムコードが実装される事を義務付けられています。

AbstractOpenAction抽象クラスのexecute()メソッドは、「メソッドの実装」です。
プログラムコードによってすでに実装されているので、abstract(抽象)とは無関係です。

抽象クラスを再利用する、クラスTimesheetOpenActionの例

以下、抽象クラスを再利用するクラスの例を書きます。
プログラムの詳細を理解する必要は、ありません。

public class TimesheetOpenAction extends AbstractOpenAction {

    public ActionForward open(ActionMapping mapping, OpenForm form,
    HttpServletRequest request, HttpServletResponse response) {

        //タイムシートファイルを開く処理
        ServletContext context = super.getServlet().getServletContext();
        XmlTimesheetManager timesheetManager = 
            (XmlTimesheetManager)context.getAttribute("timesheetManager");

        中略

    }

    中略
    
    //ここで、AbstractOpenActionクラスのexecute()を継承し、再利用します。

}

TimesheetOpenActionクラスは、open()メソッドの実装を持っています。

この「open()メソッドの実装」は、AbstractOpenAction抽象クラスの「open()メソッドの宣言」を、実装しています。

TimesheetOpenActionクラスのopen()メソッドで実装したプログラムコードは、以下の通りです。

//タイムシートファイルを開く処理
ServletContext context = super.getServlet().getServletContext();
XmlTimesheetManager timesheetManager = 
    (XmlTimesheetManager)context.getAttribute("timesheetManager");

中略

抽象クラスを再利用する、別のクラスRecordOpenActionの例

以下、抽象クラスを再利用する、「別のクラスRecordOpenActionの例」を、書きます。
プログラムの詳細を理解する必要は、ありません。

public class RecordOpenAction extends AbstractOpenAction {

    public ActionForward open(ActionMapping mapping, OpenForm form,
    HttpServletRequest request, HttpServletResponse response) {
        
        //就業記録表を開く処理
        ServletContext context = super.getServlet().getServletContext();
        XmlRecordManager recordManager = 
            (XmlTimesheetManager)context.getAttribute("timesheetManager");

        中略

    }

    中略
    
    //ここで、AbstractOpenActionクラスのexecute(…)を継承し、再利用します。

}

RecordOpenActionクラスは、open()メソッドの実装を持っています。

この「open()メソッドの実装」は、AbstractOpenAction抽象クラスの「open()メソッドの宣言」を、実装しています。

RecordOpenActionクラスのopen()メソッドで実装したプログラムコードは、以下の通りです。

//就業記録表を開く処理
ServletContext context = super.getServlet().getServletContext();
XmlRecordManager recordManager = 
    (XmlTimesheetManager)context.getAttribute("timesheetManager");

中略

AbstractOpenActionクラスのexecute()メソッドの再利用

TimesheetOpenActionクラスとRecordOpenActionクラスを比較すると、
「open()メソッドの宣言」は同じですが、「open()メソッドの実装」は違います。

「タイムシートファイルを開く処理」と「就業記録表を開く処理」のプログラムコードは、違います。

よってAbstractOpenAction抽象クラスは、
TimesheetOpenActionクラスとRecordOpenActionクラスに対して、

メソッド宣言されているopen()メソッドの実装を義務付けつつ、
AbstractOpenActionクラスのexecute()メソッドの再利用を許しているクラスと言えます。

※ここまでの記事は、2004年9月当時の記事になります。

独自処理をするメソッドの実装を義務付けて、共通処理をするメソッドを再利用する方法

抽象クラスを継承することで、
独自処理をするメソッドの実装を義務付けて、共通処理をするメソッドを再利用する方法が、あります。

Animal抽象クラスを作成する

例として、以下のようなAnimal抽象クラスを作成します。

abstract class Animal {

  // 共通の処理をするメソッド
  public void eat() {

    System.out.println("食べる");

    // 独自の処理をするメソッドを呼び出す
    makeSound();
  }

  // 独自の処理をするメソッドを宣言する
  abstract void makeSound();
}

Animal抽象クラスにおいて、共通処理をするeat()メソッドを定義します。

独自処理をするmakeSound()メソッドを、宣言します。

abstractキーワードをつけて、makeSound()メソッドの実装を省略します。

Animal抽象クラスを継承したクラスに、独自処理をするメソッドを定義する

次に、Animal抽象クラスを継承したクラスに、独自処理をするメソッドを定義します。

このメソッドは、抽象クラスで宣言されたメソッドと同じシグネチャ(名前と引数)を持ちます。

例として、以下のようなDogクラスとCatクラスを作成します。

class Dog extends Animal {

  // 独自処理をするメソッドを定義する
  void makeSound() {
    System.out.println("ワンワン");
  }
}

class Cat extends Animal {

  // 独自処理をするメソッドを定義する
  void makeSound() {
    System.out.println("ニャー");
  }
}

独自処理をするmakeSound()メソッドにプログラムコードを記述して、メソッドを実装します。

実装を義務付けた独自処理をするメソッドを呼び出す際、共通処理をするメソッドを再利用する

実装を義務付けた独自処理をするメソッドを呼び出す際、共通処理をするメソッドを再利用します。

Animal抽象クラスの共通処理をするeat()メソッド内から、
DogクラスとCatクラスに定義した独自処理をするmakeSound()メソッドを、呼び出します。

例として、以下のようなMainクラスを作成します。

class Main {
  public static void main(String[] args) {
  
    // Animal型の変数にDog型のオブジェクトを代入
    Animal dog = new Dog();

    // Animal型の変数にCat型のオブジェクトを代入
    Animal cat = new Cat();

    // 共通の処理をするメソッドを呼び出す
    dog.eat(); // 「食べる ワンワン」を出力する
    cat.eat(); // 「食べる ニャー」を出力する
  }
}

上記のソースコードにおいて、

例えばdog.eat()メソッドが実行された際、
共通処理をするeat()メソッドから、独自処理をするmakeSound()メソッドが呼び出されます。

そして、「食べる ワンワン」を出力します。

cat.eat()メソッドが実行された際も、
同様にeat()メソッドから、makeSound()メソッドが呼び出されます。

そして、「食べる ニャー」を出力します。

DogクラスとCatクラスは共に、共通処理をするeat()メソッドを再利用しています。

以上のように、抽象クラスを継承することで、共通処理をするメソッドを再利用できます。

抽象クラスには、共通処理のメソッドを定義して、インターフェース(契約)を義務付けるメソッドを宣言します。

抽象クラスを継承するサブクラスには、独自処理を行うメソッドを実装します。

そうすることによって、以下の利点があります。

  • プログラムコードの重複や冗長性を減らすこと。
  • ソースコードの可読性や保守性を向上させること。

【まとめ記事】へのリンク

【まとめ記事】Javaアプリの品質を保つため、Javaソースコードを書くための工夫

Javaソースコードを正しく書くための、ちょっとした工夫について、ご紹介しています。 変数の寿命を限定する書き方。 肯定的な条件を優先して条件分岐する書き方。 クラス…