在PHP中,可以从组成父对象的对象访问父对象吗?


In PHP, can you access a parent object from an object from which it is composed?

我有一个FileCopier的基类,它由资源源和资源目的地的两个" hasa "关联组成。

构造之后,FileCopier中存在三个属性:

- Source (instance of Resource)
- Destination (instance of Resource)
- Config (array of configuration stuff for this FileCopier)

我找到的所有关于这个问题的例子都是关于扩展的孩子,而不是通过组合的孩子。

我的问题是:是否有任何方法为资源实例访问它的父母的"配置"?

或者,我必须通过构造函数将对父类的引用传递给关联的子类吗?

如果我没理解错的话,你有:

class FileCopier{
    /* @var Source */
    private $source;
    /* @var Destination */
    private $destination;
    /* @var Config */
    private $conf;
    ...
}

你想从$source和$destination访问$conf吗?没有父变量或其他魔法字可以从其他两个变量访问这个$conf。最好的办法是在Resource中添加一个函数,它将设置一个本地引用到Config:

class Resource {
    /* @var Config */
    protected $config;
    ...
    function setConfig(Config $config) {
        $this->config = $config;
    }
    ...
}

或者如果config设置在其他点r可能会改变,或者如果因为任何其他原因你想从你的资源中访问最新的$conf,你可以传递一个ref给FileCopier:

class Resource {
    /* @var FileCopier */
    protected $copier;
    ...
    function setFileCopier(FileCopier $copier) {
        $this->copier = $copier;
        // and access to $this->copier->conf through a getter
        // or make $conf public in FileCopier
    }
    ...
}

那么你所要做的就是在使用$source和$destination之前调用setter。可能在FileCopier中:

class FileCopier{
    ...
    //first case :
    function setConfig($config) {
        $this->config = $config;
        $this->source->setConfig($config);
        $this->destination->setConfig($config);
    }
    // Or for the second case:
    function setup() {
        $this->source = new Source();
        $this->source->setFileCopier($this);
        $this->destination = new Destination();
        $this->destination->setFileCopier($this);
    }
    ...
}

答案取决于对象的职责。

如果两个资源都是由FileCopier对象创建的,您可以通过Resource类的构造函数从FileCopier提供配置(如果所有资源都应该有配置,否则通过属性/getter&;setter)。

如果FileCopier是配置的东西,并且资源将知道当前正在使用它的FileCopier(通过构造函数或属性),那么FileCopier应该只有getConfig()或使用->config(如果属性是公共的)。

从你的命名,我有一点麻烦看到实际的用例,其中一个资源必须知道对象的配置执行任何工作的资源本身。将这部分配置(即,如果它是资源上的"save"或"move"命令)移动到实际的方法调用(并调用->save(),其中FileCopier对象使用其配置中的路径)可能会更好。

如果我对问题的理解正确的话,"父母"这个词是错误的,尽管我知道你的意思。如果对象F是一个FileCopier的实例,并且有两个属性都是instanceof Resource,那么对象F不是资源实例的父对象。我不太确定该怎么称呼这种关系:-o

你可以允许资源实例访问你的配置。在你的FileCopier类中这样做:
public function setSource(Resource $r)
{
    $this->Source = $r;
    $r->setConfig($this->Config);
}