特集・コラム

メニュー

PHPer上級者になるために知っておきたいこと

vol.52 ‐ PHP『マジックメソッドを巡る旅 その1』

投稿日時:2014/08/06 03:08

カテゴリ: PHPer上級者になるために知っておきたいこと

マジックメソッド、でございます。かなり長い道中が予想されるので「旅」とか呼称してみました。
トリッキーな事もできますが、上級の試験対策にもなりますし、素直に「便利」なものも少なからずありますので、
ちょいと腰をすえて丁寧に進めていきたいと思います。

マジックメソッドは、割と平たくまとめられていて「特殊な機能を持つ」関数です。
実際には「そのメソッド名でcallされず、ある特定のイベントが発生したときに、
自動で呼ばれるメソッド」になります。

ちなみに極おおざっぱな見分け方ですが。メソッド名に「アンダースコアが二つ並んでいる」のが特徴なので、
そこを一つの手がかりにするとよいかもしれません。
ただ、フレームワークの規約などによっては「privateなメソッドは、メソッド名の先頭にアンダースコアを二つ」
という規約があるものもあるので、必ず、というわけでもないのですが。

閑話休題。

まず、一番始めに「__construct()」「__destruct()」を取り上げてみましょう。
言わずと知れた「コンストラクタ」「デストラクタ」用のメソッドですが、
実はこの子もれっきとした「マジックメソッド」だったりします。

始めにコンストラクタを解説していきましょう。
コンストラクタは「オブジェクトが生成されるタイミング(普通、new)で呼び出されるクラス関数/メソッド」で、
通常はクラス変数/プロパティの初期化とかを行ったりすることが多いもの、になります。
とりあえず、簡単なコードでコンストラクタを確認をしてみましょう。

class hoge {
public function __construct() {
echo “call hoge’s construct\n”;
}
}
//
$obj = new hoge();

__constructを明示的にcallはしていませんが、きちんと呼ばれているかと思います。
これは、newのタイミングで「暗黙的に」呼ばれているんですね。
ちなみに__constructは「特別な意味を持つメソッド」ではありますが、
とはいえ言っても「メソッド」なので、明示的に呼び出すことも、可能は可能です。まずもってやりませんが。

class hoge {
public function __construct() {
echo “call hoge’s construct\n”;
}
}
//
$obj = new hoge();
$obj->__construct();

ごく簡単なコンストラクタではありますが…実は、色々あります。
ちょっとだけ、コンストラクタの「少し深い所」を見ていきましょう。

まずは、書き方です。
現在は「マジックメソッド __construct()」ですが、以前は「クラス名と同じ名前のメソッドがあったら、
それをコンストラクタと見なす」という実装でした。

実装を見てみましょう。

class hoge {
public function hoge() {
echo “call hoge’s construct\n”;
}
}
//
$obj = new hoge();

実はこの「クラス名と同じメソッド名」という書式は、
C++とJavaで見て取ることが出来ますので、さほど奇異な実装でもないんですね。
ちなみに「マジックメソッド」のように固定のメソッド名をアサインされているのは、
Ruby#initialize、Python#__init__がそれぞれ、そうなりますので、
こちらはこちらで「PHPがお初ってわけでもない」実装方法です。

さて…では「両方かいたら」どうなるのでしょうか?
早速実験です。

class hoge {
public function __construct() {
echo “call hoge’s construct(magic method)\n”;
}
public function hoge() {
echo “call hoge’s construct(class name method)\n”;
}
}
//
$obj = new hoge();

試すと分かるのですが、マジックメソッドのほうが優先になります。
また、名前空間…というのはこのあと(マジックメソッドの次、に原稿を書く予定です)に出てくるのですが。
「名前空間つきのクラス名の最後の部分と同じ名前のメソッドは コンストラクタとみなされなくなる」と
いう状況になっている事もあるので、せっかくなら、きちんとマジックメソッドを使って書いていきたいものです。
PHP4の頃から、とか、その当時に学んだ方から教わったとか、そういう方で「クラス名をコンストラクタにする」のに慣れている方は、是非この機会に新しい方法に乗り換えていただければなぁ、と思う次第であります。

さて…コンストラクタですが、実は、ってほどでもないですが、引数を持つことができます。
実験です。

class hoge {
public function __construct($s) {
echo “call hoge’s construct({$s})\n”;
}
}
//
$obj = new hoge(“aaa”);

引数があったりなかったり…は、引数のデフォルト値、で、記述が可能です。

class hoge {
public function __construct($s = ‘default’) {
echo “call hoge’s construct({$s})\n”;
}
}
//
$obj = new hoge();

続いてコンストラクタの継承です。
普通「親クラスの(より広域的、基本的な)初期化をしてから子クラスの(より局所的な)初期化をする」事が多いので。
parent::をつかって、親のコンストラクタを呼び出すのが普通です。

class hoge {
public function __construct() {
echo “call hoge’s construct\n”;
}
}
class foo extends hoge {
public function __construct() {
// 親のコンストラクタを呼んでから
parent::__construct();
// 自分用の処理を書く
echo “call foo’s construct\n”;
}
}

また、__constructは、クラスの継承時に「引数のパターンが変わっても文句を言われない」ことを
覚えておくと良いでしょう。
まず「普通のメソッド」で、メソッドをオーバライドしたタイミングで引数の個数を変更して、怒られてみます。

class hoge {
public function test($s) {
}
public function test2($s) {
}
}
class foo extends hoge {
public function test($s, $s2) {
}
public function test2() {
}
}

引数が異なると、Warning「Strict Standards」が出てきます。
しかし、__constructは、引数が異なってもWarningは出てきません。

パターン1
class hoge {
public function __construct($s) {
}
}
class foo extends hoge {
public function __construct($s, $s2) {
}
}

パターン2
class hoge {
public function __construct($s) {
}
}
class foo extends hoge {
public function __construct() {
}
}

勿論、警句が出ないという事は「自分たちで気をつける必要がある」という事でもあるのですが、
コンストラクタで「引数が異なる」というのはあり得る状況なので、覚えておくとよいですね。

次回は、もう少しコンストラクタについて深く掘り下げてから、デストラクに歩みを進めて行きたいと思います。

バックナンバーはこちら

IT系のお仕事特集

お仕事のご紹介には、まずヒューマンリソシアへの登録が必要です。
ヒューマンリソシア人材派遣サイトの便利な機能 ・お気に入りの派遣求人のブックマーク ・登録会への予約 ・有給休暇の管理 ・WEB給与明細の確認 ・お気に入りの情報をメール受信
登録会の入力手続きをあらかじめおこなえます。

ヒューマンリソシア派遣サービスに 登録する 無料

ページトップへ戻る
ヒューマンリソシア派遣サービスに 登録する 無料
ページトップへ戻る