それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

php で prototype チェーン的なことをする

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はプロトタイプベース。ちょっとだけわかったキガス。