Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 我们可以在同一个类中声明_构造函数和类名构造函数吗?_Php_Oop_Constructor - Fatal编程技术网

Php 我们可以在同一个类中声明_构造函数和类名构造函数吗?

Php 我们可以在同一个类中声明_构造函数和类名构造函数吗?,php,oop,constructor,Php,Oop,Constructor,我们可以在同一个类中声明_构造函数和类名构造函数吗 如果是,则在创建对象时会调用这两者。还有什么顺序 如果只有一个会被呼叫,那么是哪一个?为什么呢?在这个答案的后面,你会发现你的个人问题以一种方便的列表格式得到了回答。但首先,请允许我向您提供一些一般信息、文档引用、链接和代码片段,它们将帮助您更好地理解所有这些 您可以定义这两种类型的构造函数,但PHP不会同时将这两种方法视为构造函数,因为: 为了向后兼容,如果PHP5找不到给定类的_construct()函数,并且该类没有从父类继承_const

我们可以在同一个类中声明_构造函数和类名构造函数吗

如果是,则在创建对象时会调用这两者。还有什么顺序


如果只有一个会被呼叫,那么是哪一个?为什么呢?

在这个答案的后面,你会发现你的个人问题以一种方便的列表格式得到了回答。但首先,请允许我向您提供一些一般信息、文档引用、链接和代码片段,它们将帮助您更好地理解所有这些

您可以定义这两种类型的构造函数,但PHP不会同时将这两种方法视为构造函数,因为:

为了向后兼容,如果PHP5找不到给定类的_construct()函数,并且该类没有从父类继承_construct()函数,它将根据类的名称搜索旧式构造函数。实际上,这意味着唯一存在兼容性问题的情况是,该类有一个名为_construct()的方法,该方法用于不同的语义

因此,如果未找到
\u construct
方法,则同名构造函数是一个后备方法。它的主要目的是保持与过时的PHP版本的向后兼容性,因此它是(PHP7将在今年晚些时候发布)的一种功能。PHP7将温和地反对这个“特性”,它将从PHP8中完全删除

从PHP5.3.3开始,与命名空间类名的最后一个元素同名的方法将不再被视为构造函数。此更改不会影响非命名空间的类

在PHP5.3.3及更高版本中,如果您至少使用名称空间,那么相同名称的构造函数根本不起作用

简言之:

class Foo
{
    public function Foo()
    {
        //this is the constructor
    }
}
但是:

还值得注意的是,在同一个类中定义两个可能的构造函数会发出
E_STRICT
通知。但再举几个例子

或:

所以基本上:

  • 你能定义一个同名的构造函数吗?是,如果类或其任何祖先上没有定义
    \u construct
    方法。如果存在
    \u构造函数
    方法,则同名构造函数将成为常规方法,PHP将发出
    E\u STRICT
    通知
  • 这两个方法都将被称为构造函数吗?否,如果存在
    \u构造
    方法,则该方法为构造函数。否则,将调用具有类名的方法。为什么?由于PHP5支持
    \u构造方法,PHP4构造方法是一种向后兼容的回退机制。回退永远不会优先于默认值,这就是为什么只调用
    \u构造
    方法的原因。简单
  • 定义这两种类型的构造函数会发出
    E_STRICT
    通知(在PHP5中,如果PHP7看到PHP4样式的构造函数,则会发出
    E_DEPRECATED
    通知)
  • 如果您的类是命名空间的,则它取决于PHP版本5.3.3和更高版本,它将只使用
    \u construct
    方法。鉴于我们目前使用的是版本5.6,而PHP7将于今年到期,我不会编写需要弃用PHP版本的代码
  • PHP7即将到期,并且
总而言之,很久以前,相同名称的构造函数已经被
\uu construct
取代,所以我会使用它。更多内容:使用基于名称的构造函数机制非常容易出错,因为在继承链中的某个地方发现
\uu构造
方法时,它们就会变成常规方法。使用这两种方法都会发出通知,这意味着 如果你真的想写,你可以想象,也许梦想着写一些东西,大致如下:

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原则(继承的契约违约)。

进一步回答这个问题,您会发现您的问题以方便的列表格式得到了回答。但首先,请允许我向您提供一些一般信息、文档引用、链接和代码片段,它们将帮助您更好地理解所有这些

您可以定义这两种类型的构造函数,但PHP不会同时将这两种方法视为构造函数,因为:

为了向后兼容,如果PHP5找不到给定类的_construct()函数,并且该类没有从父类继承_construct()函数,它将根据类的名称搜索旧式构造函数。实际上,这意味着唯一存在兼容性问题的情况是,该类有一个名为_construct()的方法,该方法用于不同的语义

因此,如果未找到
\u construct
方法,则同名构造函数是一个后备方法。它的主要目的是保持与过时的PHP版本的向后兼容性,因此它是(PHP7将在今年晚些时候发布)的一种功能。PHP7将温和地反对这个“特性”,它将从PHP8中完全删除

从PHP5.3.3开始,与命名空间类名的最后一个元素同名的方法将不再被视为构造函数。此更改不会影响非命名空间的类

在PHP5.3.3及更高版本中,如果您至少使用名称空间,那么相同名称的构造函数根本不起作用

简言之:

class Foo
{
    public function Foo()
    {
        //this is the constructor
    }
}
但是:

还值得注意的是,在同一个类中定义两个可能的构造函数会发出
E_STRICT
通知。但再举几个例子

或:

所以基本上:

  • 你能定义一个同名的构造函数吗?是,如果类或其任何祖先上没有定义
    \u construct
    方法。如果一个
    \uuuu con
    
    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}();
                }
            }
        }
    }
    
    <?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
        }
    }
    ?>