是否可以在一次操作中构造PHP对象并设置其变量?


Can PHP objects be constructed and their variables set in one operation?

在perl中我习惯做

my $foo = new WhatEver( bar => 'baz' );

,现在我想弄清楚PHP对象是否可以用这种方式构造。我只看到这个:

my $foo = new WhatEver();
$foo->{bar} = 'baz';

有可能一步完成吗?

你可以这样布局你的构造函数:

 class MyClass {
     public function __construct($obj=null) {
         if ($obj && $obj instanceof Traversable || is_array($obj)) {
             foreach ($obj as $k => $v) {
                if (property_exists($this,$k)) {
                    $this->{$k} = $v;
                }
             }
         }
     }
 }

这有一系列缺点:

  • 您创建的变量将不会显示在您使用的任何文档软件上
  • 这是对所有形式的懈怠敞开的大门

然而,它也有以下好处:

  • 这个可以很安全地扩展
  • 它允许你延迟实现变量
  • 它还允许你设置私有变量,只要你知道它们的名字。如果不被滥用,在这方面它是相当好的。

圆括号中传递的参数(顺便说一下,如果没有圆括号,可以省略)将传递给构造函数方法,在那里您可以对它们做任何您喜欢的事情。例如,如果定义了一个类,如下所示:

class WhatEver
{
    public $bar;
    public function __construct($bar)
    {
        $this -> bar = $bar;
    }
}

你可以给它任何你需要的值。

$foo = new WhatEver('baz');

有几种方法可以做到这一点,但每种方法都有自己的缺点。

如果你的setter返回对象本身的实例,你可以链接你的方法。

my $foo = new WhatEver();
$foo->setBar("value")->setBar2("value2");
class WhatEver
{
    public $bar;
    public $bar2;
    public function setBar($bar)
    {
        $this->bar = $bar;
        return $this;
    }
    public function setBar2($bar2)
    {
        $this->bar2 = $bar2;
        return $this;
    }
}

然而,这并没有减少到一个步骤,只是浓缩了实例化后的每一步。

参见:PHP方法链接?

你也可以在你的构造函数中声明你的属性,并在创建时将它们传递给它。

my $foo = new WhatEver($bar1, $bar2, $bar3);
然而,

的缺点是不能明显地扩展。在几个参数之后,它变得难以管理。

一种更简洁但效率较低的方法是传递一个关联数组参数,然后遍历它设置每个属性。

这里隐含的假设是对象具有有意义的(可能是公共的)属性,由调用代码为其提供值。这绝不是给定的——OOP的一个关键方面是封装,以便对象的主要访问是通过它的方法。

初始化对象状态的"正确"机制是它的构造函数,而不是一系列的属性赋值。构造函数接受什么实参取决于类定义。

现在,一个构造函数可能有一长串命名参数,所以你可以写$foo = new WhatEver(1, "hello", false, null),但如果你想让这些参数像选项一样,那么它可以接受一个散列——在PHP术语中,一个数组——作为它的参数。

所以,回答这个问题,是的,如果你的构造函数的形式是function __construct(Array $options),然后迭代或检查到$options。但如何处理这些选项取决于构造函数;例如,传递[ 'use_safe_options' => true ]可能会触发一组私有变量被设置为记录的"安全"值。

从PHP 5.4(引入[ ... ]作为array( ... )的替代品)开始,它只比Perl版本多了几个字符笔画:

$foo = new WhatEver( ['bar' => 'baz'] );