PHP 親クラスのコンストラクタ呼び出し【仕様や互換性、先祖クラスの呼出し】

PHPで親クラスのコンストラクタを呼び出す方法と、細かな注意点や仕様について解説します。

目次

親クラスのコンストラクタ呼び出し

小クラスのコンストラクタ内から親クラスのコンストラクタを呼び出したい場合には、parentキーワードを用いてparent::__construct()形式のコンストラクタ呼び出しを行う必要があります。

class A {
  // 親クラスのコンストラクタ
  function __construct() {}
}

class B extends A {
  // 子クラスのコンストラクタ
  function __construct() {
    parent::__construct(); // 親クラスのコンストラクタを呼び出す
  }
}

$b = new B(); // クラスBとAのコンストラクタメソッドが呼ばれる

このように::スコープ定義演算子でクラスのコンストラクタを表す__constructコンストラクタメソッドを直接指定して呼び出します。

親クラスのコンストラクタと細かな仕様

小クラスのコンストラクタを独自に定義した場合、親クラスのコンストラクタが暗黙的に呼び出されることはありません。

逆に小クラスのコンストラクタを定義しなかった場合には、親クラスのコンストラクタが暗黙的に継承されるため、事実上親クラスのコンストラクタが呼ばれることになります。

ただし、親クラスのコンストラクタがプライベート宣言されていた場合には、コンストラクタ呼び出しは行えません。呼び出し時にはエラーが発生します。

class T { private function __construct() {} }

class X extends T {}
new X(); // Fatal error: Call to private T::__construct() from invalid context

class Y extends T { function __construct() { parent::__construct(); } }
new Y(); // Fatal error: Cannot call private T::__construct()

class Z extends T { function __construct() {} }
new Z(); // OK

親クラス側でパブリック宣言されたコンストラクタやメソッドを、小クラス側でプライベート宣言した場合にはエラーが発生します。

class T { function __construct() {} }
class U extends T {
  // Fatal error: Access level to U::__construct() must be public (as in class T) 
  private function __construct() {}
}

クラス名形式のコンストラクタ呼び出し

親クラスのクラス名でコンストラクタを呼び出すこともできますが、クラス名形式のコンストラクタ宣言自体はPHP 7以降非推奨となっています。

class A {
  function A() {} // PHP 4以前の形式、PHP 7以降は非推奨
}

class B extends A {
  function __construct() {
    parent::A(); // PHP 4以前のコンストラクタ呼び出し
    parent::__construct(); // PHP 5以降は互換性により`A()`が呼ばれる
  }
}

逆に、親クラスのコンストラクタが__construct形式で宣言された場合は、クラス名形式でのコンストラクタ呼び出しが行えないため注意が必要です。

class C extends B {
  function __construct() {
    parent::B(); // Fatal error: Call to undefined method B::B()
    parent::__construct(); // OK(親クラスの宣言と同じ形式で呼び出す必要がある)
  }
}
参考:コンストラクタ呼び出しが失敗する場合の対象方法

先祖クラスのコンストラクタを呼び出す方法

こちらは稀なケースですが、先祖クラスや祖父クラス(親クラスの親クラス)のコンストラクタを呼び出すことも可能です。この場合はparentキーワードではなく、先祖クラスのクラス名を明示してコンストラクタ呼び出しを行う必要があります(先祖クラス名::__construct())。

class A           { function __construct() {} }
class B extends A { function __construct() {} }
class C extends B {
  function __construct() {
    A::__construct(); // OK(祖父クラスのコンストラクタが呼ばれる)
    // parent::A();   // Error: Call to undefined method B::A()
  }
}

$c = new C(); // クラスCとAのコンストラクタのみが呼ばれる

この場合、new C()によるインスタンス化の際には、クラスCとクラスAのコンストラクタのみが呼び出されることになります。クラスBのコンストラクタは呼び出されなくなります。

広告