0

いくつかのクラスのコードを節約するために、抽象クラスに取り組んでいました。これらのクラスはすべて、さまざまな静的呼び出しを通じて自身をインスタンス化するファクトリです。これらすべてのメソッドを抽象クラスに入れることで、いくつかのコードを節約できました。

しかし、遅い静的バインディングの問題に遭遇しました... 私たちの Web ホストは 5.3 以降を使用していないため、get_called_class にアクセスできません。私が持っている場合

$class = __CLASS__;
return new $class();

抽象クラスで__CLASS__は、呼び出されたクラスを実際に使用したい場合の抽象クラスの名前です。

子クラスが独自のインスタンス化メソッドを持ち、抽象化された親に依存していない Web 上の抽象ファクトリの例を見てきました。ただし、この場合、抽象クラスを使用する唯一の理由はコードを保存することなので、そこでそれができなければ、その価値は大幅に低下します。

PHP < 5.3 で回避策はありますか? debug_backtrace()?


編集:

私はテストを行いましたが、うまくいかdebug_backtrace()ないようです!これがlate static bindingが必要な理由だと思います。

<?

abstract class abstractFactory {
    public function create() {
            print_r(debug_backtrace());
            $class = __CLASS__;
            return new $class();
    }
}

class concreteFactory extends abstractFactory {}

$chimborazo = concreteFactory::create();

そして結果:

$ php test.php
Array
(
    [0] => Array
        (
            [file] => /var/www/test.php
            [line] => 13
            [function] => create
            [class] => abstractFactory
            [type] => ::
            [args] => Array
                (
                )

        )

)

Fatal error: Cannot instantiate abstract class abstractFactory in /var/www/test.php on line 7
4

3 に答える 3

1

これについて私が確認した唯一の回避策は、debug_backtraceを呼び出して呼び出し元のクラス名を特定することです。もちろん、これは巨大なハックです。バックトレースと実際に呼び出し元のファイルを開き、それを解析して物事を理解することを組み合わせたコードを見てきました。奇妙で恐ろしいもの。

LSB の不足は戻ってきて、後であなたを苦しめます。ホストの切り替えを意味する場合でも、今すぐアップグレードしてください。実際、ホストの切り替えを意味する場合は特にそうです。5.3 がリリースされてから 1 年が経ちました。

于 2010-08-13T18:54:56.773 に答える
1

5.3に移行するまで私が使用していたものは次のとおりです。

if (!function_exists('get_called_class')) {

   /**
    * Implementation of get_called_class() for pre-5.3 PHP
    *
    * @return string
    */
   function get_called_class()
   {
      $bt = debug_backtrace();
      $lines = file($bt[1]['file']);
      preg_match('/([a-zA-Z0-9\_]+)::'.$bt[1]['function'].'/',
               $lines[$bt[1]['line']-1],
               $matches);
      return $matches[1];
   }
}

これにより、関数が呼び出されたクラス名を静的関数で決定できます。これはいくつかのパフォーマンスの問題がある回避策ですが、私が見つけた唯一の回避策です。他にあれば知りたいです。

于 2010-08-13T18:55:26.667 に答える
0

これを行う 1 つの方法は、さまざまなインスタンス化メソッドをオーバーライドし、クラスの名前を直接渡すことです。

<?

abstract class abstractFactory {

    public function create($class) {
        return new $class();
    }

    public function instantiate($class) {
        return new $class();
    }

}

class concreteFactory extends abstractFactory {

    public function create() {
        parent::create(__CLASS__);
    }

    public function instantiate() {
        parent::instantiate(__CLASS__);
    }
}


$chimborazo = concreteFactory::create();
$chimborazo = concreteFactory::instantiate();
于 2010-08-13T18:59:53.860 に答える