2011年10月21日金曜日

オーバーライド時のアクセス修飾子変更 PHP 編

オーバーライド時にアクセス修飾子の変更を検証。

まず、親クラス。
class ParentClass
{
  private function func1() { echo "Parent private func1\n"; }
  protected function func2() { echo "Parent protected func2\n"; }
  public function func3() { echo "Parent public func3\n"; }

  public function call()
  {
    $this->func1();
    $this->func2();
    $this->func3();
  }
}
private, protected, public の 3 種類のメソッドと、それらを呼び出すメソッドを作成。

子クラス1 は public に変更。
class Child1Class extends ParentClass
{
  public function func1() { echo "Child1 private -> public func1\n"; }
  public function func2() { echo "Child1 protected -> public func2\n"; }
  public function func3() { echo "Child1 public func3\n"; }
}
シンタックスエラーは起きない。

子クラス2 は protected に変更。
class Child2Class extends ParentClass
{
  protected function func1() { echo "Child2 private -> protected func1\n"; }
  protected function func2() { echo "Child2 protected func2\n"; }
  // Access level to Child2Class::func3() must be public (as in class ParentClass)
  // protected function func3() { echo "Child2 protected -> protected func3\n"; }
}
func3 の変更でエラーとなる。public を protected に変更できないようだ。

子クラス3 は private に変更。
class Child3Class extends ParentClass
{
  private function func1() { echo "Child3 private func1\n"; }
  // Access level to Child3Class::func2() must be protected (as in class ParentClass)
  // private function func2() { echo "Child3 protected -> private func2\n"; }
  // Access level to Child3Class::func3() must be public (as in class ParentClass)
  // private function func3() { echo "Child3 public -> private func3\n"; }
}
func2, func3 でエラーとなる。やはり、厳しい方向への変更はできないようだ。

実行してみると、
$p = new ParentClass();
$p->call();
echo "----------\n";
$c1 = new Child1Class();
$c1->call();
echo "----------\n";
$c2 = new Child2Class();
$c2->call();
echo "----------\n";
$c3 = new Child3Class();
$c3->call();
 
結果は、
Parent private func1
Parent protected func2
Parent public func3
----------
Parent private func1
Child1 protected -> public func2
Child1 public func3
----------
Parent private func1
Child2 protected func2
Parent public func3
----------
Parent private func1
Parent protected func2
Parent public func3

親クラスは当然の結果が出ている。
子クラス1の func1 は、親クラスの func1 が private なためオーバーライドできずに、親クラスの func1 が呼ばれている。
子クラス2の func1 も同様。func2, func3 はオーバーライドしていないためそのまま親クラスのものが呼ばれている。
それぞれの子クラスで、call を再定義してやると、それぞれの func1 が呼ばれる。

protected -> public への変更はできるが、public -> protected -> private への変更はできない。
private はオーバーライドできない。

0 件のコメント:

コメントを投稿