我们可以在同一个类中声明__constructor和类名构造函数吗?
如果是,则在创建对象时都会调用它们。这也将是序列。
如果只有一个会被调用,那么哪一个?为什么?
答案 0 :(得分:3)
在此答案的下方,您会发现您的个人问题以便捷的列表格式得到了解答。但首先,请允许我向您提供一些一般信息,文档引用,链接和代码片段,以帮助您更好地理解这一切。
您可以定义两种类型的构造函数,但PHP永远不会将这两种方法同时视为构造函数,如is explained here:
为了向后兼容,如果PHP 5找不到给定类的__construct()函数,并且该类没有从父类继承,它将搜索旧式构造函数,其名称为类。实际上,这意味着唯一具有兼容性问题的情况是该类是否有一个名为__construct()的方法,该方法用于不同的语义。
因此,如果找不到__construct
方法,则同名构造函数是后备。它的主要目的是保持与无望的过时PHP版本的向后兼容性,因此它是will be removed in the next major release of PHP(PHP7将在今年晚些时候推出)的东西。 PHP7将轻轻地弃用此"功能" ,并且它将从PHP8中完全删除
从PHP 5.3.3开始,与命名空间类名的最后一个元素同名的方法将不再被视为构造函数。此更改不会影响非命名空间的类。
对于PHP 5.3.3及更高版本,如果您至少使用名称空间,那么相同名称的构造函数将无法完成
简而言之:
class Foo
{
public function Foo()
{
//this is the constructor
}
}
但:
class Foo
{
public function __construct()
{
//this is the constructor
}
public function Foo()
{
//this is just a method
}
}
同样值得注意的是,在同一个类中定义两个可能的构造函数会发出E_STRICT
通知。但是有了例子......
或:
class Bar
{
public function __construct()
{
//this is the constructor
}
}
class Foo extends Bar
{
public function Foo()
{
//this is a regular function
//Bar::__construct is the constructor
}
}
和
namespace Foo\Bar;
class Foo
{
public function Foo()
{
//this is just a method
//Foo\Bar\Foo is a class without a constructor
}
}
基本上是这样的:
__construct
方法。如果存在__construct
方法,则同名构造函数将成为常规方法,PHP将发出E_STRICT
通知__construct
方法,那就是构造函数。如果没有,将调用具有类名的方法。为什么?因为PHP5支持__construct
方法,所以PHP4构造函数是向后兼容的回退机制。回退永远不会优先于默认值,这就是为什么只调用__construct
方法。简单。E_STRICT
通知(在PHP5中,如果PHP7看到PHP4样式的构造函数,PHP7将发出E_DEPRECATED
通知。)__construct
方法。鉴于我们目前的版本为5.6,而PHP7将于今年发布,我不会编写需要弃用PHP版本的代码总而言之,很久以前,同名构造函数已被__construct
取代,所以我会使用它。更重要的是:使用基于名称的构造函数机制非常容易出错,因为在继承链的某个地方找到__construct
方法时,它们会变成常规方法。使用两个发出通知,这意味着significant performance hit
如果 真的 想要,那么可能可能会想到可能会梦想写下以下内容:
class Foo
{
private $constructed = false;
public function __construct()
{
if ($this->constructed === false)
{
$this->Foo();
}
}
public function Foo()
{
$this->constructed = true;
//do constructor stuff...
}
}
在混音中添加继承,你最终会得到这个:
class BaseClass//the parent
{
protected $constructed = false;
final public function __construct()
{
if ($this->constructed === false)
{
$class = explode('\\', get_class($this));
$method = end($class);
if (method_exists($this, $method))
{
//use func_get_args_array() + call_user_func_array
//if your constructor takes arguments:
call_user_func_array(
array($this, $method),
func_get_args_array()
);
$this->constructed = true;
//simple version: $this->{$method}();
}
}
}
}
但是,让我们诚实一下,这真的是一件愚蠢的事情,不会吗?那个,并且通过使用这种方法没有解决通知,所以你仍然必须考虑那些通知。如果您的子类构造函数需要参数,那么,至少在第二种情况下,您的构造函数会破坏liskov原则(继承的合同违规)。
答案 1 :(得分:0)
是的,你可以,但它对我有意义,你为什么要这样做, 如果您喜欢某些功能,请使用承包商覆盖。 在PHP 5.3.3中,类名方法被视为正常函数, 例如。
<?php
namespace Foo;
class Bar {
public function Bar() {
// treated as constructor in PHP 5.3.0-5.3.2
// treated as regular method as of PHP 5.3.3
}
}
?>
它在版本5.3.3或更高版本中的意思是你必须声明像__construct
这样的构造函数
如果同时使用它们,则类名构造函数将不起作用。