登録した関数をオブジェクト内部から呼び出す事と、メソッドの動的な生成です。
同日修正:コード修正しました。
すみません。ポカミスってました。呼び出される関数で $this に受け取っていたので、$slf へ受け取ります。
■ 2009/04/24追記
php:インスタンスのクラスを変えてしまう
こういうやり方でも擬似的に追加や変更が出来る
外部の関数を内部からの呼出す。
まずは簡単なところから。
class foo{
function run($i){// 関数起動用のメソッド
$i($this);
}
}
// 以下確認用コード
// 呼出す関数
function cb_func(&$slf){echo 'call back : ' . get_class($slf);}
// 確認用コード
$obj = new foo();
$obj->run('cb_func');// 結果 call back : foo
function run($i){// 関数起動用のメソッド
$i($this);
}
}
// 以下確認用コード
// 呼出す関数
function cb_func(&$slf){echo 'call back : ' . get_class($slf);}
// 確認用コード
$obj = new foo();
$obj->run('cb_func');// 結果 call back : foo
単に内部から呼出すだけのもの。呼出す側の関数は、$this を受け取ってやる必要があります。ただ、これだけでは、オブジェクトを受け取ってそのオブジェクトにアクセスする外部の関数やオブジェクト(※1)となんら変わらない。(ハズw)
つまり上記コードだと $obj->run('cb_func'); ではなく cb_func($obj); で十分。
ちなみに呼出す関数の &$slf は必須。ま、当然かな。^^
内部のメソッドからの参照と呼出し。
class foo{
function set($i){// 関数登録用のメソッド
$this->delegation = $i;// 関数「名」を登録
}
function run(){// 関数起動用のメソッド
$fn = $this->delegation;
$fn($this);
}
}
// 以下確認用コード
// 呼出す関数
function cb_func(&$slf){echo 'call back : ' . get_class($slf);}
// 実装
$obj = new foo();
$obj->set('cb_func');
$obj->run();// 結果 call back : foo
function set($i){// 関数登録用のメソッド
$this->delegation = $i;// 関数「名」を登録
}
function run(){// 関数起動用のメソッド
$fn = $this->delegation;
$fn($this);
}
}
// 以下確認用コード
// 呼出す関数
function cb_func(&$slf){echo 'call back : ' . get_class($slf);}
// 実装
$obj = new foo();
$obj->set('cb_func');
$obj->run();// 結果 call back : foo
関数名をインスタンスの変数に登録しているに過ぎないのですが、※1が代理(Proxy)とすれば、こちらは委譲(Delegation)という概念に近いものではないかな。
委譲についてはこちら。 http://www.weblio.jp/content/%E5%A7%94%E8%AD%B2
ちゃんと内部のメソッドから登録されたメソッドを呼出しています。$this を与えているので、追加されたメソッドは当然オブジェクトへアクセスできます。
これは単一のメソッドのみの登録になります。
複数のメソッドを登録。
class foo{
function set($i){// 関数登録用のメソッド
$this->$i = $i;
}
function run($i){// 関数起動用のメソッド
$fn = $this->$i;
$fn($this);
}
}
// 以下確認用コード
// 呼出す関数
function cb_func1(&$slf){echo 'call back1 : ' . get_class($slf);}
function cb_func2(&$slf){echo 'call back2 : ' . get_class($slf);}
// 実装
$obj = new foo();
$obj->set('cb_func1');
$obj->set('cb_func2');
$obj->run('cb_func1');// 結果 call back1 : foo
$obj->run('cb_func2');// 結果 call back2 : foo
function set($i){// 関数登録用のメソッド
$this->$i = $i;
}
function run($i){// 関数起動用のメソッド
$fn = $this->$i;
$fn($this);
}
}
// 以下確認用コード
// 呼出す関数
function cb_func1(&$slf){echo 'call back1 : ' . get_class($slf);}
function cb_func2(&$slf){echo 'call back2 : ' . get_class($slf);}
// 実装
$obj = new foo();
$obj->set('cb_func1');
$obj->set('cb_func2');
$obj->run('cb_func1');// 結果 call back1 : foo
$obj->run('cb_func2');// 結果 call back2 : foo
固定された変数に登録(上記前項)するか、変数を動的に作成するかの違いだけです。
内部にもともとあるメソッド(ネイティブ)から呼出すには、配列へ登録した方が参照しやすいかも。
これで、自由に追加(というより登録かな)して、ネイティブなメソッドから呼出すことができます。
動的な生成は、create_function で可能です。
create_function はクラス内部で使っても $this が渡されないので、上記のサンプルの呼出す関数と同様に扱います。
つまり内部で生成しても外部で生成しても変わらない。
うーむ。気に入らないのは。
$obj->cb_func();
などの様に呼出せないところかな。そもそも $this->cb_func などで可変関数が使えないのが根源。ネイティブなメソッドなら $this->cb_func(); で呼出せますが、可変関数は一旦別の変数に入れてやらないと呼出せない。
なので、可変関数を呼出すメソッドなどが必要になってしまう。上記コードだと run すね。とは言え、それはそれで、ネイティブとの区別がはっきりして良いのですけど。
ま、PHP ユーザ会のマニュアルにも PHP5 はオブジェクト指向の言語じゃない(PHP4 じゃなく!?)と書いてある分けですし。無理矢理ですが、それでも結構有用じゃないかな。
実践で使った事ないけどw そもそも object 指向すらそんなに・・・爆



この記事へのコメント