在php中初始化类成员的最佳实践


10

我的构造函数中有很多这样的代码:-

function __construct($params) {

    $this->property = isset($params['property']) ? $params['property'] : default_val;

}

这样做比在属性定义中指定默认值好吗?即public $property = default_val?有时默认值存在逻辑,某些默认值取自其他属性,这就是为什么我在构造函数中执行此操作。

我应该使用设置器,以便将默认值的所有逻辑都分开吗?

Answers:


8

我以前与我自己进行过这种哲学辩论。尽管我意识到这是一个基于意见的答案,但我在大多数时间都站在这里:

我看到的可能有助于回答这个问题的一件事是$ params的传递,该参数可以设置也可以不设置属性/数组成员。

多年来,我得出了以下结论:

避免传递数组。

为什么?好吧,没有办法为可选的传递参数设置或定义哨兵值。

换句话说,使用您指定的代码,您将无法执行以下操作:

function __construct($arg1 = NULL, $arg2 = DEFAULT_VAL) {

    $this->arg1 = $arg1;

    $this->arg2 = $arg2;

}

$ arg1和$ arg2是可选参数-如果未传递,则分别具有NULL和DEFAULT_VAL-无需显式检查。

也许这有点武断。

我想我得到了您想要完成的任务-传递单个引用而不是大量争论。这使我得出下一个结论:

如果未传递“原子”变量(字符串,整数,文字),则传递对象。

因为传递对象是通过引用完成的,所以这里有性能上的好处(尽管我认为数组在PHP中大致相同)。

因此,您可以执行以下操作:

function __construct(MyAwesomeObject $oArg) {

        $this->oArg = $oArg;

    }

这样就可以保证传递的对象参数具有“ property1”,“ property2”,尽管它们本身可能具有默认值。

此外,在这里您可以键入提示,一个好的IDE也会正确地自动建议代码完成。

但是我们很快意识到我们正在发生鸡鸡和鸡蛋的事情:您正在构建带有传递的对象参数的对象,而对象参数本身在某些时候需要构造。

那么,这在哪里呢?好吧,我得出的结论是,由于缺乏更好的术语,所有类最终都归结为“原子”变量(字符串,浮点数,双精度数,整数,资源,我明白了),并且我倾向于尝试用那些变量类型或对象(而不是数组)构造所有类。

那我回答了你的问题吗?可能不完全正确。但我希望我能说明一些有用的内容,尽管有些风格。我认为代码更简洁,可读性更好,成本更低。

现在,这并不是说您不应该清理输入内容。完全是另一回事。

希望这可以帮助。


1
这是一个好点,对于IDE提示非常方便,但是对象属性太多,无法将它们全部作为参数传递。如果您有7个参数,则说其中5个是可选的,那么您最终会得到类似的信息new object($param1,-some default value so I can specify the next parameter-, $param3);,因此您会将默认值硬编码在几个不同的地方
rgvcorley 2012年

3

尽管我倾向于避免将数组传递给构造函数,但有时我发现有必要处理传入的数组值(例如对于从配置文件中读取值的类)。

在这种情况下,我将利用PHP的数组函数来确保我使用的正是我认为的东西:

public function import( array $incoming )
{
  $defaults = array(
      'foo' => DEFAULT_FOO
    , 'bar' => DEFAULT_BAR
    ...
  );

  $values = array_merge($defaults, array_intersect_key($incoming, $defaults));

  ...
}

最后一行使用的对应值array_merge()覆盖中的任何值。我还要确保结果数组不包含类/方法不知道如何处理的任何额外键。$defaults$incomingarray_intersect_key()


您好,如果$ defaults包含数组而不是简单变量,该怎么办?
Pol Dellaiera 2014年

@PolDellaiera看看array_merge_recursive
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.