is_callable() のススメ

PHP で、クラスに関数が定義されている場合のみ当該関数を call する〜なんてことをする際に、下記のようなコードを書いていたのですが、、、

<?php
if (method_exists($hoge, 'func')) {
    $hoge->func();
}

「これって、func() が存在するけどその scope から呼べないケースどうなるん?private 関数とか。」という声を聞いて、これはまずそうだなと。
こんなとき、is_callable() ってのを使うと良いみたい。
PHP: is_callable - Manual
以下、サンプルコード。

<?php
class Hoge {
    public function this_is_public() {}
    protected function this_is_protected() {}
    private function this_is_private() {}
}

$hoge = new Hoge();
if (method_exists($hoge, 'this_is_public')) { echo 'aaa' . PHP_EOL; }
if (method_exists($hoge, 'this_is_protected')) { echo 'bbb' . PHP_EOL; }
if (method_exists($hoge, 'this_is_private')) { echo 'ccc' . PHP_EOL; }
if (is_callable(array($hoge, 'this_is_public'))) { echo 'ddd' . PHP_EOL; }
if (is_callable(array($hoge, 'this_is_protected'))) { echo 'eee' . PHP_EOL; }
if (is_callable(array($hoge, 'this_is_private'))) { echo 'fff' . PHP_EOL; }

$hoge->this_is_public();
//$hoge->this_is_protected(); // Fatal error: Call to protected method Hoge::this_is_protected() from context '' in ...
//$hoge->this_is_private(); // Fatal error: Call to private method Hoge::this_is_private() from context '' in ...
$ php ./test.php
aaa
bbb
ccc
ddd

method_exists() はアクセス指定が何であろうと、関数さえ定義されてれば true 判定。
is_callable() はアクセス可能な場合のみ、true 判定。
冒頭のケースでは、明らかに後者のが適切ですね。。。

試しに上のクラスを継承したら protected な関数も is_callable() = true と判定されました。

<?php
class Hoge { ... }
class Fuga extends Hoge {
    public function test() {
        if (is_callable(array($this, 'this_is_public')))    { echo 'ddd' . PHP_EOL; }
        if (is_callable(array($this, 'this_is_protected'))) { echo 'eee' . PHP_EOL; }
        if (is_callable(array($this, 'this_is_private')))   { echo 'fff' . PHP_EOL; }
    }
}

$fuga = new Fuga();
$fuga->test();
$ php ./test.php
aaa
bbb
ccc
ddd
ddd
eee