【PHP】アクセス修飾子とオーバーライド - オーバーライド可否とアクセス修飾子の種類
アクセス修飾子によってオーバーライド可能なメソッドが制限されます。
ここでは、アクセス修飾子とオーバーライドの関係について解説します。
検証環境
アクセス修飾子とオーバーライド
オーバーライドするメソッドは、アクセス修飾子の種類(public
/ protected
/ private
)によって次の2点の制限が付与されます。
- オーバーライド可否
- アクセス修飾子の種類
1.オーバーライド可否
オーバーライド可否は“オーバーライドが可能かどうか”です。
アクセス修飾子がprivate
なメソッドはオーバーライドできません。
protected
またはpublic
なメソッドのみオーバーライドが可能です。
アクセス修飾子の種類
オーバーライドするメソッドのアクセス修飾子によって、付与できる種類(アクセス権)が異なります。
アクセス権はオーバーライドするメソッドより厳しくすることができません。
アクセス修飾子はprivate
>protected
>public
の順で制限されています。
そのため、例えば、スーパークラスがprotected
の場合、サブクラスではpublic
またはprotected
のアクセス修飾子のみでオーバーライドできます。
アクセス修飾子とオーバーライドの関係性をまとめると次の表のようになります。
オーバーライド対象メソッドの
アクセス修飾子 |
public | protected | private |
---|---|---|---|
オーバーライド可否 | ○ | ○ | × |
アクセス修飾子の種類 | public |
public
protected |
public
protected
private |
サブクラスでアクセス修飾子がprivate
なスーパークラスのメソッドと同名のメソッドを定義すると、オーバーライド(再定義)ではなく“新しいメソッドの定義”とみなされます。
そのような場合は、全種類のアクセス修飾子を使うことが可能です。
制限の確認
アクセス修飾子とオーバーライドの関係性について、実際に確認します。
<?php
class AccessOverride {
public function method_public() { echo "method_public : SUCCESS!\n"; }
protected function method_protected() { echo "method_protected : SUCCESS!\n"; }
private function method_private() { echo "method_private : SUCCESS!\n"; }
public function execute() {
$this->method_public();
$this->method_protected();
$this->method_private();
}
}
class SubAccessOverride extends AccessOverride {
public function method_public() { echo "sub_method_public : SUCCESS!\n"; }
protected function method_protected() { echo "sub_method_protected : SUCCESS!\n"; }
private function method_private() { echo "sub_method_private : SUCCESS!\n"; }
}
$test = new SubAccessOverride();
$test->execute();
?>
$ php sample.php
sub_method_public : SUCCESS!
sub_method_protected : SUCCESS!
method_private : SUCCESS!
SubAccessOverride
クラスはAccessOverride
クラスを継承し、各メソッド(execute
メソッドを除く)をオーバーライドしています。
実行結果から分かるようにSubAccessOverride
クラスのオブジェクトからexecute
メソッドを呼び出すと、public
とprotected
なメソッドはサブクラスのメソッドが実行されました。
しかし、private
なメソッドはオーバーライドできないため、スーパークラスのメソッドが実行されています。
このexecute
メソッドをサブクラスに定義すると、動作が変わります。
<?php
class AccessOverride {
public function method_public() { echo "method_public : SUCCESS!\n"; }
protected function method_protected() { echo "method_protected : SUCCESS!\n"; }
private function method_private() { echo "method_private : SUCCESS!\n"; }
___ih_diff_start
- public function execute() {
- $this->method_public();
- $this->method_protected();
- $this->method_private();
- }
___ih_diff_end
}
class SubAccessOverride extends AccessOverride {
public function method_public() { echo "sub_method_public : SUCCESS!\n"; }
protected function method_protected() { echo "sub_method_protected : SUCCESS!\n"; }
private function method_private() { echo "sub_method_private : SUCCESS!\n"; }
___ih_diff_start
+ public function execute() {
+ $this->method_public();
+ $this->method_protected();
+ $this->method_private();
+ }
___ih_diff_end
}
$test = new SubAccessOverride();
$test->execute();
?>
$ php sample.php
sub_method_public : SUCCESS!
sub_method_protected : SUCCESS!
sub_method_private : SUCCESS!
実行結果からサブクラスの各メソッドが実行されていることが分かります。
これは、execute
メソッドがサブクラスで定義されていることにより、サブクラス起点でメソッドを呼び出すためです。
また、オーバーライドのアクセス修飾子の制限を1段階厳しく(public
→protected
、protected
→private
)してみます。
<?php
class AccessOverride {
public function method_public() { echo "method_public : SUCCESS!\n"; }
protected function method_protected() { echo "method_protected : SUCCESS!\n"; }
private function method_private() { echo "method_private : SUCCESS!\n"; }
}
class SubAccessOverride extends AccessOverride {
___ih_diff_start
- public function method_public() { echo "sub_method_public : SUCCESS!\n"; }
+ protected function method_public() { echo "sub_method_public : SUCCESS!\n"; }
- protected function method_protected() { echo "sub_method_protected : SUCCESS!\n"; }
+ private function method_protected() { echo "sub_method_protected : SUCCESS!\n"; }
private function method_private() { echo "sub_method_private : SUCCESS!\n"; }
___ih_diff_end
public function execute() {
$this->method_public();
$this->method_protected();
$this->method_private();
}
}
$test = new SubAccessOverride();
$test->execute();
?>
$ php sample.php
PHP Fatal error: Access level to SubAccessOverride::method_public() must be public (as in class AccessOverride) in sample.php on line 13
このコードは実行するとエラーが発生します。
原因はオーバーライドするメソッドより、アクセス権を厳しくしたためです。
実行結果では13行目でエラーが発生し、処理が止まっていますが、14行目でも同様のエラーになります。
このようにオーバーライドはスーパークラスのアクセス修飾子より厳しくすることはできません。