2006年12月18日

PHP4コアでメソッドの動的な追加

PHP4 コアのみで、PECLの runkit 関数を使わずにメソッドの動的な追加(っぽい事)をやってみます。

登録した関数をオブジェクト内部から呼び出す事と、メソッドの動的な生成です。

同日修正:コード修正しました。
すみません。ポカミスってました。呼び出される関数で $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

単に内部から呼出すだけのもの。呼出す側の関数は、$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

関数名をインスタンスの変数に登録しているに過ぎないのですが、※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

固定された変数に登録(上記前項)するか、変数を動的に作成するかの違いだけです。
内部にもともとあるメソッド(ネイティブ)から呼出すには、配列へ登録した方が参照しやすいかも。
これで、自由に追加(というより登録かな)して、ネイティブなメソッドから呼出すことができます。

動的な生成は、create_function で可能です。
create_function はクラス内部で使っても $this が渡されないので、上記のサンプルの呼出す関数と同様に扱います。
つまり内部で生成しても外部で生成しても変わらない。


うーむ。気に入らないのは。
$obj->cb_func();
などの様に呼出せないところかな。そもそも $this->cb_func などで可変関数が使えないのが根源。ネイティブなメソッドなら $this->cb_func(); で呼出せますが、可変関数は一旦別の変数に入れてやらないと呼出せない

なので、可変関数を呼出すメソッドなどが必要になってしまう。上記コードだと run すね。とは言え、それはそれで、ネイティブとの区別がはっきりして良いのですけど。

注意)オブジェクトから呼び出しているのは、あくまで外部の関数です。
機能的に近いことができるって感じです。
他に補足が要るのは、すぐ上の「可変関数は」云々かな。それはまた後日w
補足はこちら

ま、PHP ユーザ会のマニュアルにも PHP5 はオブジェクト指向の言語じゃない(PHP4 じゃなく!?)と書いてある分けですし。無理矢理ですが、それでも結構有用じゃないかな。
実践で使った事ないけどw そもそも object 指向すらそんなに・・・爆


posted by HiFa at 03:55 | 🌁 | Comment(0) | TrackBack(0) | ときどきPHP | このブログの読者になる | 更新情報をチェックする
>>> スパムコメントは消してますよん。 お互い無駄な労力は避けましょう。 <<<

この記事へのコメント

コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/29842434
※言及リンクのないトラックバックは受信されません。

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。