2009年01月14日

php:インスタンスのクラスを変えてしまう

php で擬似的に以下2つ
・ インスタンスのクラスを変更
・ メソッドの動的な追加

幾つかのオブジェクトシステムではインスタンスのクラスを変えられますが、それを php で真似る。

■ まずは結果
// 変換先クラスサンプル
class foo{
  public $p = 'yo!';
  public function dump(){var_dump($this);}
}

// 変更させるインスタンス
$obj = new stdClass;
$obj->d = 'hi!';

// 変更前のvar_dump
var_dump($obj);// object(stdClass)#1 (1) { ["d"]=> string(3) "hi!" }
echo "<br><br>";

// クラスを変えてしまう
change_class(&$obj, 'foo');

// 変更後のvar_dump
$obj->dump();// object(foo)#2 (2) { ["p"]=> string(3) "yo!" ["d"]=> string(3) "hi!" }
echo "<br><br>";

// foo そのものから作ると
$foo = new foo;
var_dump($foo);// object(foo)#1 (1) { ["p"]=> string(3) "yo!" }
echo "<br><br>";

// 一見するとメソッドの動的な追加のような事も
add_method(&$obj, 'public function hello(){echo "hello!<br />";}');
$obj->hello();// hello!

// メソッド追加後の var_dump
$obj->dump();// object(add_method_0)#3 (2) { ["p"]=> string(3) "yo!" ["d"]=> string(3) "hi!" }
echo "<br><br>";


■ 自前の環境
PHP Version 5.2.3
System Windows NT
Server API Apache 2.0



 クラスを変更する関数他

// インスタンスのクラスを変える
function change_class(&$obj, $new){
  $old = get_class($obj);
  $ser = serialize($obj);
  $ser = preg_replace("/O:\d+:\"$old\"/", "O:" . strlen($new) . ":\"$new\"", $ser);
  $obj = unserialize($ser);
}

// 一見クラスメソッドを動的に追加したような事もできる。
function add_method(&$obj, $mtd){
  static $num = 0;
  $old = get_class($obj);
  $new = 'add_method_' . $num++;
  $ext = "class $new extends $old { $mtd }";
  eval($ext);
  $ser = serialize($obj);
  $ser = preg_replace("/O:\d+:\"$old\"/", "O:" . strlen($new) . ":\"$new\"", $ser);
  $obj = unserialize($ser);
  return $ext;
}


キッタネーと思った方。正解です。(コードの美醜じゃなくw)
結局のところ serialize / unserialize です。

そして「まねると危険」なコードです。
間違っても安易にセッションに入れたりはしないでください。
何にせよ、カチっとした php では、お行儀が良いようには見えない。
無理矢理ですしねぇ。

ただ、結局の所、セッションでの復元の際、クラスの定義内容を変える場合と同じ事になります。
include するファイルを変えるなどですね。
そう言った点で意識して使ってる人もあるかもしれません。

私はそんな流動的なアルゴリズムは怖くて(仕事では)書けませんがw
それと、javascript メインな人にも抵抗感が無いかも知れない。
仕様として実装されてる CLOS系のオブジェクトシステム の人にも出来て当然かも知れません。

ただこれ、クラスを渡り歩けるので面白いです。

※ serialize しているので serialize の機能による制約があります。
※ あーそうそう。preg_replace はいい加減なので(色々とかw)気を付けてください。


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

この記事へのコメント

コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

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


※画像の中の文字を半角で入力してください。

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

PHP4コアでメソッドの動的な追加
Excerpt: こちらは試行錯誤的なもの
Weblog: Script雑感
Tracked: 2009-04-24 14:05