PHP名称空间和继承


PHP Namespaces and inheritance

我正在将我开发的一系列类转换为使用名称空间。
其中一个类有一个依赖项:

文件

namespace VENDOR
class A{
    static public function(){
        B::getInfo();
    }
}
文件B

namespace VENDOR;
class B{
    static public function getInfo(){
       //some work
    }
}

然后,这属于我将包含到项目中的个人库。B类易扩展:

namespace APPNAMESPACE
class SuperB extends 'VENDOR'B{
    static public function getInfo(){
        //Some different work
    }
}

我的意图是VENDOR'A调用APPNAMESPACE'SuperB,但在这里我看到我没有设计好我的系统,因为显然它将继续调用VENDOR' b。

在此之前,我可以实现这种行为,因为我根本没有使用名称空间,而是使用经典的类命名约定DIR_CLASS.php,它允许我的自动加载器(现在使用composer)首先在高优先级的APP文件夹中查找,如果没有在其他优先级较低的文件夹中找到(类似于kohana, Codeigniter等)。

那么我如何处理这个(显然没有硬编码APPNAMESPACE'SuperB到VENDOR'A)

如果没有状态,这很快就会变得棘手。这个是静态调用的原因吗?如果可能的话,我倾向于使用(可配置的、可测试的、可交换的、可测试的)实例。

这样做要容易得多:

namespace VENDOR
class A{
    protected $b;
    public function __construct(B $b){
        $this->b = $b;
    } 
    public function something(){
        $this->b->getInfo();
    }
}

…所以你可以加入你喜欢的东西。可能,构造函数中的B类型提示更应该是一个接口,而不是一个类定义,并且您可能无法控制外部供应商为您提供的内容。

如果我们假设你不能碰VENDOR的代码,我认为没有合理的工作方法。如果它需要是静态的(并且需要长时间思考为什么会这样),并且可以触摸代码,这样做可能会起作用,但我不喜欢它,因为它更难检查,调试和强制类名的一致性(OTOH,未经测试):

namespace VENDOR
class A{
    protected static $b = 'B';
    static public function something(){
        call_user_func(array(self::$b,'getInfo'));
    }
    static function useB($classname){
        if(!in_array(''VENDOR'B',class_implements($classname))){
            trigger_error("$classname does not implement 'VENDOR'B", E_USER_ERROR);
        }
        self::$b = 
    }
}

再次选择一个接口而不是一个实现来检查。但是,如果您想进一步扩展'VENDOR'A,我们可能会再次遇到static::/self::问题。这是"一种"的功能,你看到@ $PDO->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'A class that extends PDOStatement');的例子,但你已经立即看到,它被调用在一个实例(和事实,它需要扩展而不是实现PDOStatement有更多的c级实现/该类的功能)。