如何在PHP中实现拷贝构造函数?

How to implement a copy constructor in PHP?

我有一个 class Account,它有一个默认的构造函数:

class Account {

    AccountType $type;
    AccountLabel[] $labels;
    AccountAttribute[] $attributes;

    // Initializes a new account and assigns labels to the new account.
    public function __construct(
        AccountType $type,
        AccountLabel[] $labels,
        AccountAttribute[] $attributes)
    {
        $this->type = $type;
        $this->labels = $labels;
        $this->attributes = $attributes;
    }

    // Other parts of the class are omitted here.
}

我需要为此实现一个复制构造函数class,以便可以通过从另一个帐户复制数据来构建一个新帐户。

在其他 OOP 语言中,这可以通过为默认构造函数创建重载以接收帐户的另一个实例 class 进行复制来完成。但是,PHP 不允许有两个具有相同名称的函数,无论参数是否不同,包括 __construct() 函数。

我不能将 $labels 参数设为可选参数,因为它实际上是创建新帐户所必需的。仅添加一个新参数使其成为可选可能会导致许多误报测试结果。所以,这个实现应该是最后的手段:

class Account {

    AccountType $type;
    AccountLabel[] $labels;
    AccountAttribute[] $attributes;

    // Initializes a new account and assigns labels to the new account;
    // Or, copy from another account.
    public function __construct(
        AccountType $type,
        AccountLabel[] $labels,
        AccountAttribute[] $attributes,
        Account $that)
    {
        if ($that === null) {
            $this->type = $type;
            $this->labels = $labels;
            $this->attributes = $attributes;
        } else
        {
            // Copy from another account.
            $this->type = $that->type;
            $this->labels = $that->labels;
            $this->attributes = $that->attributes;
        }
    }

    // Other parts of the class are omitted here.
}

我也知道神奇的 __clone 回调函数。但是,我正在寻找实现复制构造函数的方法,而不是变通方法。

您有 2 个选择:

  1. 创建 1 个构造函数并检查参数以弄清楚意图是什么。
  2. 创建工厂方法。您可以在同一个 class 中或在 class.
  3. 之外以静态方法的形式执行此操作

我认为 #2 更好,因为您仍然可以通过键入获得好处 + 您可以使用非常有意的措辞来命名方法。

PHP不支持函数重载。

PHP 不支持方法重载,并且不能为 class.

创建多个构造函数

实现所需功能的常用方法是实现 so-called "named constructor",这只是一个静态工厂方法:

class Account {

    AccountType $type;
    AccountLabel[] $labels;
    AccountAttribute[] $attributes;

    // The regular constructor
    public function __construct(
        AccountType $type,
        AccountLabel[] $labels,
        AccountAttribute[] $attributes,
    {
        $this->type = $type;
        $this->labels = $labels;
        $this->attributes = $attributes;
    }

    // A "named constructor" that works similar to a copy constructor 
    public static copyFrom(Account $account)
    {
        // Do not re-implement the constructor
        return new self($account->type, $account->labels, $account->attributes);
    }

    // Other parts of the class are omitted here.
}

阅读 this article 了解更多示例。

为什么 __clone 功能对您不起作用?

您可以像这样克隆一个对象,默认的__clone函数将所有变量复制到新实例。

$a = new Account(....);
$b = clone $a;

但是如果您不想复制所有变量,那么您可以覆盖 class

中的 __clone 函数
class Account {
    ....
    public function __clone() {
        $this->type = null;
        ....
    }
}