PHPでオブジェクト指向プログラミングを行う際、クラスの継承を行うことは当たり前に行われます。その際、子クラスから親クラスのメソッドの呼び出し方について迷ったことはありませんか?
具体的にはparent::method();
と $this->method();
のどちらを使用すべきか……という疑問です。
PHPを何となくで長年使い続けてきた自分としては、やはり何となくの理解で使用してきました。特に問題が無ければいつも$this
の方です。
……でも、parent
でも(大抵は)動きます。人に教える際、教え方に迷うことがあり、きちんと調べてみました。
これら二つの呼び出し方の違いと、どのような状況でどちらを使用するべきなのかを解説します。
どちらでも動くケース
まず、以下の様に使用している場合、どちらでも動きます。どちらでも動いてしまうからこそ、なんとなく使ってしまいがちなのだろうと思います。
class ParentClass {
public function method() {
echo 'Parent method';
}
}
class ChildClass extends ParentClass {
public function callMethod() {
$this->method(); // This will output 'Parent method'
parent::method(); // This will output 'Parent method'
}
}
$child = new ChildClass();
$child->callMethod();
※継承しているので、$thisでも親のメソッドを呼べることを意味します。
実例から見る$thisとparentの違い
どちらを使うべきかを考える際に、実例から考えてみたいと思います。
parent::method(); の使用例
parent::method();
を使うと、親クラスのメソッドを直接呼び出します。
想定利用ケース:
子クラスが同じ名前のメソッドをオーバーライド(上書き)していて、それにもかかわらず親クラスのメソッドを呼び出したい場合に使用します。
class ParentClass {
public function method() {
echo 'Parent method';
}
}
class ChildClass extends ParentClass {
public function method() {
echo 'Child method';
}
public function callMethod() {
parent::method(); // This will output 'Parent method'
}
}
$child = new ChildClass();
$child->callMethod();
$this->method(); の使用例
一方、$this->method();
を使うと、そのインスタンス(オブジェクト)が現在持っているメソッドが呼び出されます。
子クラスがメソッドをオーバーライドしている場合、$this->method();
はオーバーライドされたメソッドを呼び出します。
class ParentClass {
public function method() {
echo 'Parent method';
}
}
class ChildClass extends ParentClass {
public function method() {
echo 'Child method';
}
public function callMethod() {
$this->method(); // This will output 'Child method'
}
}
$child = new ChildClass();
$child->callMethod();
なんでどちらでも動くか
最初のコードを再掲します。以下はなぜどちらでも動くのでしょうか。
class ParentClass {
public function method() {
echo 'Parent method';
}
}
class ChildClass extends ParentClass {
public function callMethod() {
$this->method(); // This will output 'Parent method'
parent::method(); // This will output 'Parent method'
}
}
$child = new ChildClass();
$child->callMethod();
継承している関係上、クラスメソッドは自分($this)でもあり、親(parent)でもあると考えれば感覚的に理解できそうです。
結論:どちらを使えば良いか
正解は、あなたのコード&意図次第……ということになると思います。
つまりは確実に親のメソッドを呼びたいか、そうでないか。どちらを意図するかにより変わります。
メソッドをオーバーライドしている場合
メソッドをオーバーライドしている場合、親のメソッドを呼びたければparent
一択。同様に子のメソッドを呼びたければ$this
一択です。
そうでないと、意図したメソッドが呼び出されないからです。これは分かりやすいですね。
オーバーライドしていない場合は!?
オーバーライドしてない時にどうすればいい?
オーバーライドしていない場合、$this->method();
と parent::method();
のどちらを使用しても同じ結果が得られます。大抵の場合はコード補完だって利くでしょう。
だからこそ、どっちを使えば良いの!?と迷ってしまう方もいるかもしれません。
個人的には、以下の理由から $this->method();
を私は推奨します。
$this->method();
は現在のインスタンス(オブジェクト)のコンテクストでメソッドを呼び出すため、一貫性がある。特に大規模なプロジェクトやチームで作業するときに重要かもしれない(→というかチームのやり方に従いましょう)。- メソッドが将来的にオーバーライドされる可能性がある場合、
$this->method();
を使用していると、その変更を自然に反映できる。つまり、子クラスでメソッドがオーバーライドされた場合でも、そのメソッド呼び出しは自動的に新しい実装を使用できる。
私の気づかないメリット・デメリットもあるかもしれません。新たに分かったことがあれば訂正します。
余談:staticなメソッドの場合
その場合は、self::
かparent::
かで選ぶことになります。
class ParentClass {
public static function method() {
echo 'Parent method';
}
}
class ChildClass extends ParentClass {
public static function method() {
echo 'Child method';
}
public function callMethod() {
self::method(); // This will output 'Child method'
parent::method(); // This will output 'Parent method'
}
}
$child = new ChildClass();
$child->callMethod();
これは直感通りの呼び出し結果です。self::
と併せ、parent::
にはスタティックっぽいイメージがあるので、そのせいで混乱してしてまうように思うんですよねー。
$this->
に対しては$parent->
などの予約語があれば直感的?なのかもしれません……今さら無理でしょうね。
まとめ
PHPのクラスとメソッドを使いこなすためには、メソッドの呼び出し方について理解することが重要です。
parent::method();
と $this->method();
は似ているように見えますが、それぞれ異なる目的と状況で使われることをご紹介しました。
parent::method();
は親クラスのメソッドを明示的に呼び出したい場合に使います。$this->method();
は現在のオブジェクトのメソッドを呼び出すため、より一般的な用途に適しています。特に、メソッドが将来的にオーバーライドされる可能性がある場合には、$this->method();
の使用が推奨されます。
きちんと理解した上で、適切な方を選べると良いですね!
コメント