PHPでは、5.3から「無名関数」という文法が増えました。英語表記で「Anonymous functions」とされる通り「Anonymous(名前のない)」関数です。リスト11のように書きます。
<?php // $func = function () { echo "Anonymous function\n"; }; // $func();
無名関数は、例えば「関数自体、を関数の戻り値として返す」であるとか、あるいは「関数の引数で『callable』とされているところに直接関数を書く」などの用途で使われることがあります。関数の引数に直接関数を書くのは、JavaScriptだと比較的なじみがあるものかと思います。
比較的よく見掛ける無名関数の使い方としては、例えば「set_error_handler()関数を使って、標準の関数についても、エラーであれば例外をthrowする」というものです。リスト12は、実際に「関数の引数に、直接無名関数を記述している」書き方です。
set_error_handler( function($errno, $errstr, $errfile, $errline) { throw new ErrorException($errstr, 0, $errno, $errfile, $errline); });
さて、この「無名関数」ですが、実際にはPHPでどのように実装されているのでしょうか?
まずは、リスト11に少し手を入れて、確認してみましょう。
<?php // $func = function () { echo "Anonymous function\n"; }; // $func(); var_dump($func);
実行すると、下記のようになります。
Anonymous function object(Closure)#1 (0) { }
このように、実際には無名関数はインスタンスになっています。
無名関数は内部的には、「__invoke()」というマジックメソッドを使っています。冒頭で述べた通りマジックメソッドは一定の条件の下に暗黙で呼ばれるメソッドですが、別に明示的に呼んではいけないわけではないので、明示的に呼んでみましょう(リスト14)。
<?php // $func = function () { echo "Anonymous function\n"; }; // $func->__invoke();
動かしてみると分かる通り、結果13と同じ動きをします。
__invokeマジックメソッドはインスタンスを関数としてコールしようとした際に呼ばれるマジックメソッドなので、例えばリスト15のようなコードを書くことができます。
<?php // class hoge { public function __invoke() { echo "call method\n"; } } // $obj = new hoge(); $obj();
普段は無名関数の書式で使うことが多いので、__invoke自体を実際に実装するという機会は少ないかと思いますが、「こんなことができる」というのを知っておくと、ひょんなところで役に立つかもしれません。
前述のように__invokeはインスタンスを関数として扱う場合に使いますが、インスタンスを文字列のように扱う場合、__toStringを使います。「toString」というメソッド名自体は、実はJavaやC#など、いくつかの言語にも見られるメソッドです。ログへの出力などの状況で、うまく使っていくと便利です。
実際に、コードを書いて検証してみましょう。まずは、__toStringがない場合です。
<?php // class hoge { } // $obj = new hoge(); $s = 'data is ' . $obj; echo "{$s}\n";
実行すると、「Catchable fatal error: Object of class hoge could not be converted to string」というエラーになります。
続いて、__toStringを実装してみましょう。
<?php // class hoge { public function __toString() { return "hoge to string"; } } // $obj = new hoge(); $s = 'data is ' . $obj; echo "{$s}\n";
実行すると、下記のようになります。
data is hoge to string
なお、「インスタンスの保存」という意味では、連載第6回で説明を予定している「シリアライズ」の方が便利なので、そちらも参照してもらえればと思います。
今回は、比較的PHPに固有な仕様である「マジックメソッド」のいくつかについて説明しました。
次回は、オブジェクト指向系の言語で割と広く見られる「interface」、抽象メソッド、多重継承の系列の一つである「trait」などについて解説します。
Copyright © ITmedia, Inc. All Rights Reserved.