0

我正在研究一个抽象类,以节省几个类的一些代码。这些类都是通过不同的静态调用实例化自己的工厂。我可以通过将所有这些方法放在一个抽象类中来节省一些代码。

但是,我遇到了后期静态绑定问题……因为我们的网络主机没有使用 5.3 或更高版本,所以我无权访问 get_call_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
4

3 回答 3

1

我见过的唯一解决方法是调用debug_backtrace来确定调用者的类名。这当然是一个巨大的黑客。我已经看到了一些将回溯与实际打开调用文件并对其进行解析以解决问题的代码。奇怪的,可怕的东西。

LSB 的缺乏会在以后回来咬你。立即升级,即使这意味着切换主机。事实上,特别是如果这意味着切换主机。5.3 已经发布一年了。

于 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

一种方法是重写各种实例化方法,并直接传递类的名称:

<?

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 回答