コンストラクタから別のコンストラクタを呼び出す

オブジェクトが作成されると自動的にコンストラクタが呼び出されます。また、コンストラクタの中から別のコンストラクタを呼び出すこともできます。このような仕組みをコンストラクタチェーンといいます。別のコンストラクタを呼び出すことで、コードの重複を避けたりデフォルト値の設定を効率よく行うことができます。ここではオブジェクト指向におけるコンストラクタチェーンの使い方について解説します。

コンストラクタチェーンとは

クラスで複数のコンストラクタを定義している場合、あるコンストラクタの中から別のコンストラクタを呼び出すことができます。このようにコンストラクタから別のコンストラクタを呼び出すことをコンストラクタチェーンといいます。

コンストラクタから別のコンストラクタを呼び出す場合、呼び出す側のコンストラクタの中で this() を使用します。 なお this() を使用する場合は、必ずコンストラクタの最初の行に記述する必要があります。

// 引数のないコンストラクタを呼び出します
this()

// 引数が 1 つのコンストラクタを呼び出します
this(引数)

// 引数が 2 つのコンストラクタを呼び出します
this(引数1, 引数2)

次の例では引数のないコンストラクタの中から、引数が 2 つあるコンストラクタを呼び出しています。

class Product {
  private int price;
  private String name;

  public Product() {
    this(0, "未定");
  }

  public Product(int price, String name) {
    this.price = price;
    this.name = name;
  }
}

引数のないコンストラクタが呼ばれた場合、引数が 2 つあるコンストラクタを呼び出しています。

※ 引数が 2 つあるコンストラクタの中で、 this.price のような記述がされていますが、この this はコンストラクタチェーンの this() とは関係がありません。こちらの this に関して詳しくは「thisキーワード」を参照されてください。

今度は逆に引数が 1 つあるコンストラクタから引数のないコンストラクタを呼び出しています。

class Product {
  private int price;
  private String name;

  public Product() {
  	this.price = 0;
  	this.name = "未定";
  }

  public Product(String name) {
    this();
    this.name = "レモン";
  }
}

引数が 1 つあるコンストラクタが呼ばれた場合、引数がないコンストラクタを呼び出しています。

this()を呼び出す位置

既に記載したとおり this() を使用する場合は、必ずコンストラクタの最初の行に記述する必要があります。

Product() {
  this(100);
  System.out.println("完了しました");
}

別の処理を実行したあとで this() を呼び出すとコンパイルエラーとなります。

Product() {
  System.out.println("完了しました");
  this(100);
}

※ this() を使用する場合は先頭行でなければならないという仕様は現在変更されており、先頭行以外でも this() を呼び出すことができるようになりました。

コンストラクタチェーンを使うメリット

コンストラクタから別のコンストラクタを呼び出すと次のようなメリットがあります。

一つ目は「コードの重複を避ける」です。複数のコンストラクタで共通する初期化処理がある場合、いずれかのコンストラクタにまとめておき、他のコンストラクタから呼び出すことでコードの重複を防ぐことができます。

下記ではオブジェクトが作成されたときに必ず行う処理を一つのコンストラクタに記述しておき、他のコンストラクタから呼び出すことで同じ処理を何度も書かないようにしています。

class Product {
  int price;
  String name;

  Product() {
    // 初期化に伴うさまざまな処理
    System.out.println("オブジェクトが作成されました");
    System.out.println("このオブジェクトは価格および名前のデータを持ちます");
  }

  Product(int price, String name) {
    this();
    this.price = price;
    this.name = name;
  }
}

二つ目は「デフォルト値の提供」です。特定の引数が省略されてコンストラクタが呼ばれた場合に、デフォルト値を指定した上ですべての引数を取るコンストラクタを呼び出すために使われます。

下記では stock を指定しないコンストラクタが呼ばれた場合に、デフォルト値として 0 を指定した上で他のコンストラクタを呼び出しています。

class Product {
  int price;
  String name;
  int stock;

  Product(int price, String name) {
    this(price, name, 0);
  }

  Product(int price, String name, int stock) {
    this.price = price;
    this.name = name;
    this.stock = stock;
  }
}

コンストラクタチェーンを上手く使用することで、プログラムがコンパクトになり、修正が必要になったときの修正漏れを防ぐことができます。

-- --

オブジェクト指向におけるコンストラクタチェーンの使い方について解説しました。

( Written by Tatsuo Ikura )

プロフィール画像

著者 / TATSUO IKURA

これから IT 関連の知識を学ばれる方を対象に、色々な言語でのプログラミング方法や関連する技術、開発環境構築などに関する解説サイトを運営しています。