連載
» 2015年09月04日 05時00分 公開

PHPオブジェクト指向プログラミング入門(4):便利だけど使いどころが難しいPHPの代表的なマジックメソッドと無名関数の使い方 (3/3)

[古庄道明,株式会社格子組]
前のページへ 1|2|3       

無名関数と、そこで使われている__invoke()

PHP 5.3から使えるようになった「無名関数」とは

 PHPでは、5.3から「無名関数」という文法が増えました。英語表記で「Anonymous functions」とされる通り「Anonymous(名前のない)」関数です。リスト11のように書きます。

<?php
//
$func = function () {
    echo "Anonymous function\n";
};
//
$func();
リスト11

 無名関数は、例えば「関数自体、を関数の戻り値として返す」であるとか、あるいは「関数の引数で『callable』とされているところに直接関数を書く」などの用途で使われることがあります。関数の引数に直接関数を書くのは、JavaScriptだと比較的なじみがあるものかと思います。

 比較的よく見掛ける無名関数の使い方としては、例えば「set_error_handler()関数を使って、標準の関数についても、エラーであれば例外をthrowする」というものです。リスト12は、実際に「関数の引数に、直接無名関数を記述している」書き方です。

set_error_handler( function($errno, $errstr, $errfile, $errline) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
});
リスト12

無名関数は、どう実装されているのか

 さて、この「無名関数」ですが、実際にはPHPでどのように実装されているのでしょうか?

 まずは、リスト11に少し手を入れて、確認してみましょう。

<?php
//
$func = function () {
    echo "Anonymous function\n";
};
//
$func();
var_dump($func);
リスト13

 実行すると、下記のようになります。

Anonymous function
object(Closure)#1 (0) {
}
結果13

 このように、実際には無名関数はインスタンスになっています。

インスタンスを関数として扱う__invoke()

 無名関数は内部的には、「__invoke()」というマジックメソッドを使っています。冒頭で述べた通りマジックメソッドは一定の条件の下に暗黙で呼ばれるメソッドですが、別に明示的に呼んではいけないわけではないので、明示的に呼んでみましょう(リスト14)。

<?php
//
$func = function () {
    echo "Anonymous function\n";
};
//
$func->__invoke();
リスト14

 動かしてみると分かる通り、結果13と同じ動きをします。

 __invokeマジックメソッドはインスタンスを関数としてコールしようとした際に呼ばれるマジックメソッドなので、例えばリスト15のようなコードを書くことができます。

<?php
//
class hoge {
    public function __invoke() {
        echo "call method\n";
    }
}
//
$obj = new hoge();
$obj();
リスト15

 普段は無名関数の書式で使うことが多いので、__invoke自体を実際に実装するという機会は少ないかと思いますが、「こんなことができる」というのを知っておくと、ひょんなところで役に立つかもしれません。

__toString()でインスタンスを文字列にする

 前述のように__invokeはインスタンスを関数として扱う場合に使いますが、インスタンスを文字列のように扱う場合、__toStringを使います。「toString」というメソッド名自体は、実はJavaやC#など、いくつかの言語にも見られるメソッドです。ログへの出力などの状況で、うまく使っていくと便利です。

 実際に、コードを書いて検証してみましょう。まずは、__toStringがない場合です。

<?php
//
class hoge {
}
//
$obj = new hoge();
$s = 'data is ' . $obj;
echo "{$s}\n";
リスト16

 実行すると、「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";
リスト17

 実行すると、下記のようになります。

data is hoge to string
結果17

 なお、「インスタンスの保存」という意味では、連載第6回で説明を予定している「シリアライズ」の方が便利なので、そちらも参照してもらえればと思います。

次回は、interface、抽象メソッド、traitなどについて

 今回は、比較的PHPに固有な仕様である「マジックメソッド」のいくつかについて説明しました。

 次回は、オブジェクト指向系の言語で割と広く見られる「interface」、抽象メソッド、多重継承の系列の一つである「trait」などについて解説します。

筆者紹介

古庄道明

1970年浅草生まれ。1995年に富士通系のソフトハウスに就職しプログラマーに転身。1999年個人事業主として独立し現在に至る。「寺子屋」「格子組」といったエンジニア支援活動を独自に展開し、占い師時代の「ガルーダ」という占い師名にちなんだ「がる先生」の愛称で親しまれている。

コンサルティングからシステム設計、ネットワークにセキュリティと、守備範囲は比較的多岐にわたる。「技術の基本は、その技術がないときの“困ってる”が根っこ」をモットーに、古い話から現代へ歴史をたどるように教えるのが持ち味。


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。