思考实现:在没有反射的情况下,基于常量实例化类


Pondering implementation: Instantiate class based on constant without reflection

第二次更新

我想我处理这个问题的角度不对。假设我应该将"First"作为一个抽象类,并在以后找到引用"Second"answers"Third"的方法,这是正确的吗?

更新

根据一些反馈,我添加了一些内容,试图明确我想做什么。类似于这种效果。

我从下面的代码中知道,"如果"它确实有效,这是对性能的浪费,因为它不起作用,我知道我从错误的角度来处理这个问题。根据我使用过的一些框架的猜测,最终目标并不罕见。

我更试图将这段特定的代码建立在CodeIgniter方法的基础上,在该方法中,您可以在配置文件中定义(以下内容)STR_CLASS_NAME,然后在程序操作的任何时候,按照我的指示使用它。

STR_CLASS_NAME = 'Second';
class First {
    protected $intTestOne = 100;
    public function __construct() {
         $strClassName = STR_CLASS_NAME;
         return new $strClassName();
    }
    public function TestOne() {
        echo $this->intTestOne;
    }
    protected function TestThreePart() {
        return '*Drum ';
    }
}
class Second extends First{
    /* Override value to know it's working */
    protected $intTestOne = 200;
    /* Overriding construct to avoid infinite loop */
    public function __construct() {}
    public function TestTwo() {
        echo 'Using method from extended class';
    }
    public function TestThree() {
        echo $this->TestThreePart().'roll*';
    }
}
$Test = new First();
$Test->TestOne(); <-- Should echo 200.
$Test->TestTwo(); <-- Should echo 'Using method from extended class'
$Test->TestThree(); <-- Should echo '*Drum roll*'

你可能会问,为什么要这样做,而不仅仅是实例化第二,好吧,有些情况下它略有不同:

STR_CLASS_NAME = 'Third';
class Third extends First{
    /* Override value to know it's working */
    protected $intTestOne = 300;
    /* Overriding construct to avoid infinite loop */
    public function __construct() {}
    public function TestTwo() {
        echo 'Using method from extended class';
    }
    public function TestThree() {
        echo $this->TestThreePart().'snare*';
    }
}
$Test = new First();
$Test->TestOne(); <-- Should echo 300.
$Test->TestTwo(); <-- Should echo 'Using method from extended class'
$Test->TestThree(); <-- Should echo '*Drum snare*'

情况

我有一个抽象类,它用实际实现扩展了基类;在这种情况下是一个基本的DB包装器。

class DBConnector ()
class DBConnectorMySQLi extends DBConnector()

正如您所看到的,MySQLi就是实现。现在,根据配置过程中的一个值,一个常量将成为我希望使用的类名,在这种情况下(如下所示构建DBConnectorMySQLi.

define('STR_DB_INTERFACE', 'MySQLi');
define('DB_CLASS', 'DBConnector'.STR_DB_INTERFACE);

目标

  • 拥有一个可以扩展为包含实现的基类
  • 代码本身不需要知道实现的实际名称
  • To(在本例中)能够键入或使用项目接受的公共变量来创建DBConnectorMySQLi。例如$db或类似的东西。W

问题

当涉及到实际调用这个类时,我希望代码如下所示。我想知道在不需要添加任何额外语法的情况下,这是否可行。顺便说一句,这个常数是100%保证可以定义的。

$DBI = new DB_CLASS();

解决方案1

我知道使用反射类是可能的(如本问题中所讨论的),这是通过实现的

$DBI = new ReflectionClass(DB_CLASS);

然而,这会创建比预期"更脏"的代码

解决方案2

在DBConnector的构造函数中启动DBConnectorMySQLi的特定实现。

define('STR_DB_INTERFACE', 'MySQLi');
define('DB_CLASS', 'DBConnector'.STR_DB_INTERFACE);
class DBConnector() { public function __construct() { $this->objInterface = new DBConnectorMySQLi(); }
class DBConnectorMySQLi()

然而,这将导致需要继续将变量从一个"推送"到另一个

任何建议都非常感谢

实例化类时可以使用变量。

$classname = DB_CLASS;
$DBI = new $classname();

来源:从PHP中的一个变量实例化一个类?