php で prototype 的なことをやろうと思った。
php の rar をExtendsしようとしたけど、extends できない
<?php class RarByEntryName /* extends RarArchive */ { //←Extendsしたいけどfinal 出来ない }
final で拡張を閉じられている。どうするか?
継承できないなら 移譲する。
継承できないものは、移譲する。これデザインパターン入門でならいました。
<?php class RarByEntryName /* extends RarArchive */ { //←Extendsしたいけど出来ない protected $super; // 親クラスのフリをさせる移譲 public function __get($name){ if(property_exists($this,$name)) { return $this->$name; } // 移譲 if(property_exists($this->super,$name)) { return $this->super->$name; } // 移譲 $ret = $this->super->$name; if( $ret ){ return $ret; } throw new Exception("Undefined property {$name}"); } //メソッド移譲 public function __call($name, $args){ return call_user_func_array([ $this->super, $name], $args ); } }
これってメソッドチェーン・・・
これって、移譲パターンというよりプロトタイプパターンに見えてきた。
ああ、だから、Javascriptってクラスの継承がないのか。
<?php class prototype { public function __get($name){ if(property_exists($this,$name)) { return $this->$name; } // 移譲 if(property_exists($this->super,$name)) { return $this->super->$name; } // 移譲 $ret = $this->super->$name; if( $ret ){ return $ret; } throw new Exception("Undefined property {$name}"); } //メソッド移譲 public function __call($name, $args){ return call_user_func_array([ $this->super, $name], $args ); } } class A extends prototype { public function __construct(){ $this->super = new PDO("sqlite:./test.db"); } } class B extends prototype { public function __construct(){ $this->super = new A(); } } class C extends prototype { public function __construct(){ $this->super = new B(); } } $c = new C();
これで、C -> B -> A -> PDO の関係を作ることが出来る
実際にヤってみた
<?php $c = new C(); $sh = $c->prepare("select * from users where name = :name ;"); var_dump($sh);
object(PDOStatement)#5 (1) { ["queryString"]=> string(40) "select * from users where name = :name ;" }
ちゃんと、プロトタイプでメソッドチェーンを構成できた。ダイヤモンド継承的なことができてる。
ああ、だから動的型付け言語にはクラスがあってないようなものなのね。
クラスで欲しいのは、変数(関数)の束縛と変数(関数)の名前空間とスコープだわ。
究極的にはスクリプト言語は継承が「いつでも作れる」だからJSはああいう削ぎ落とした構成なんだ。
JSはプロトタイプベース。ちょっとだけわかったキガス。