抽象的な工場<5.3では不可能ですか?
-
28-09-2019 - |
質問
いくつかのクラスのコードを保存するために、抽象クラスに取り組んでいました。これらのクラスはすべて、さまざまな静的呼び出しを通じて自分自身をインスタンス化する工場です。これらすべてのメソッドを抽象クラスに配置することで、いくつかのコードを保存できます。
しかし、私はaに出会いました 後期静的結合 問題... Webホストは5.3以降を使用していないため、get_called_classにアクセスできません。私が持っているなら
$class = __CLASS__;
return new $class();
抽象クラスでは、 __CLASS__
抽象クラスの名前であり、実際に呼び出されたクラスを使用したいときです。
子どものクラスに独自のインスタンス化方法があり、抽象的な親に頼らない抽象的な工場の例をウェブ上で見てきました。ただし、この状況では、抽象クラスの唯一の理由はコードを保存することです。そのため、そこでできない場合、その価値は大幅に減少します。
PHP <5.3に回避策はありますか? debug_backtrace()
?
編集:
私はテストをしたようです debug_backtrace()
動作しないでしょう!これが必要な理由だと思います 後期静的結合.
<?
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
解決 3
それを行う方法は、さまざまなインスタンス化方法をオーバーライドし、クラスの名前を直接渡すことです。
<?
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();
他のヒント
これについて私が見た唯一の回避策には、呼び出しが含まれます debug_backtrace 発信者のクラス名を決定します。これはもちろん巨大なハックです。バックトレースを組み合わせたコードを見てきました 実際に呼び出しファイルを開いて解析します 物事を理解するために。奇妙で恐ろしいもの。
LSBの欠如が戻ってきて、後であなたを噛むでしょう。ホストの切り替えを意味する場合でも、今アップグレードしてください。実際、特にホストの切り替えを意味する場合。 5.3はもう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];
}
}
これにより、静的関数で、関数が呼び出されたクラス名を決定できます。パフォーマンスの問題がいくつかある回避策ですが、私が見つけたのはそれだけです。他の人がいるなら、私は知りたいと思っています。