70

__construct()在 PHP 中使用而不是类的名称作为构造函数有什么好处吗?

示例 ( __construct):

class Foo {
    function __construct(){
        //do stuff
    }
}

示例(命名):

class Foo {
    function Foo(){
        //do stuff
    }
}

从 PHP 5 开始就可以使用该__construct方法(第一个示例)。

从 PHP 版本 4 到版本 7,可以使用与类同名的方法作为构造函数(第二个示例)。

4

11 回答 11

71

我同意小发明,优点是如果你重命名你的类,你不必重命名它。干燥。

同样,如果您有一个子类,您可以调用

parent::__construct()

调用父构造函数。如果进一步更改子类继承的类,则不必更改对父类的构造调用。

这似乎是一件小事,但是缺少将构造函数调用名称更改为您的父类可能会产生微妙的(而不是那么微妙的)错误。

例如,如果您将一个类插入到您的 heirachy 中,但忘记更改构造函数调用,您可以开始调用祖父母的构造函数而不是父母的构造函数。这通常会导致难以察觉的不良结果。

另请注意

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

来源: http: //php.net/manual/en/language.oop5.decon.php

于 2008-10-20T09:25:22.893 回答
20

__construct在 PHP5 中引入。这是你现在应该这样做的方式。不过,我不知道本身有任何优势。

来自 PHP 手册:

为了向后兼容,如果 PHP 5 找不到给定类的 __construct() 函数,它将按类的名称搜索旧式构造函数。实际上,这意味着唯一会出现兼容性问题的情况是,如果该类有一个名为 __construct() 的方法,该方法用于不同的语义

如果您使用的是 PHP5,我建议您使用__construct它来避免让 PHP 看起来别处。

于 2008-10-20T05:57:11.673 回答
16

我看到 __construct 的主要优点是,如果更改类名,则不必重命名构造函数。

于 2008-10-20T06:01:11.930 回答
11

今天,公认的答案已经过时了。

重命名类是不好的做法:每次升级到较新版本时,您都必须记住要重命名的内容和位置。有时(比如使用反射或复杂的依赖结构)如果不进行彻底的重构是不可能的。这是您要避免的意外复杂性。这就是命名空间被引入 PHP 的原因。Java、C++ 或 C# 不使用__construct,它们使用命名构造函数,它们没有问题。

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

例子

namespace Foo;
class Test {
  var $a = 3;

  function Test($a) {
    $this->a = $a;
  }

  function getA() {
    return $this->a;
  }
}

$test = new Test(4);
echo $test->getA(); // 3, Test is not a constructor, just ordinary function

请注意,不推荐使用命名构造函数(今天的 PHP 5.5)。但是,您无法预测您的类不会在命名空间中使用,因此 __construct应该优先使用。

澄清上述不良做法(针对丹尼斯)

您可以在代码中的某处使用ReflectionClass::getName();当你重命名类时,你需要记住你在哪里使用了反射,并检查getName()结果在你的应用程序中是否仍然一致。您需要记住的特定内容越多,就越有可能忘记某些内容,从而导致应用程序出现错误。

父母无法控制世界上所有依赖他们的班级。如果启用了allow_url_include,则其他一些网站可能正在使用您服务器中的类,如果您重命名某个类,它可能会崩溃。在上面提到的编译语言中情况更糟:该库可以复制并捆绑在其他代码中。

没有理由重命名类:

  • 如果类名冲突,使用命名空间
  • 如果类责任转移,则派生一些其他类

在命名空间中的 PHP 类中,无论如何都应该避免使用同名的方法:直观地说,它应该产生一个创建该类的对象;如果它做其他事情,为什么要给它同样的名字?它应该是一个构造函数,没有别的。主要问题是这种方法的行为取决于命名空间的使用。

PHP 中的 __construct 构造函数没有问题。但改变命名构造函数并不是最聪明的主意。

于 2013-06-16T09:14:03.653 回答
8

使用__contruct()而不是的最大优势ClassName()是在扩展类时。parent::__construct()调用它而不是更容易parent::ClassName(),因为它可以在类之间重用,并且可以轻松更改父级。

于 2008-10-20T09:30:19.030 回答
7

在您的示例Foo::Foo中,有时称为 PHP 4 或旧式构造函数,因为它来自 PHP 4 时代:

class Foo {
    // PHP 4 constructor
    function Foo(){
        //do stuff
    }
}

PHP 4 构造函数将被弃用,但不会在 PHP 7 中删除。在 PHP 8 的任何情况下,它们都将不再被视为构造函数。未来的兼容性绝对是不使用此功能的一个重要原因。

于 2015-05-13T03:03:48.823 回答
4

好吧,这个问题被问到已经有几年了,但我想我仍然必须回答这个问题,因为事情已经发生了变化,对于未来的读者,我希望让信息保持最新!


因此在 php-7 中,他们将删除将构造函数创建为与类同名的函数的选项。如果你仍然这样做,你会得到一个E_DEPRECATED.

您可以在此处阅读有关此提案的更多信息(该提案已被接受): https ://wiki.php.net/rfc/remove_php4_constructors

并从那里引用:

只要定义了 PHP 4 构造函数,PHP 7就会发出E_DEPRECATED。当方法名与类名匹配时,该类不在命名空间中,并且 PHP 5 构造函数 (__construct) 不存在,则将发出 E_DEPRECATED。PHP 8 将停止发出 E_DEPRECATED 并且这些方法将不会被识别为构造函数。

E_STRICT如果你定义一个与类和 a 同名的方法,你也不会在 php-7 中得到a __construct()

你也可以在这里看到:

当存在与类同名的方法以及 __construct 时,PHP 7也将停止发出 E_STRICT 。


所以我建议你使用__construct(),因为将来你会遇到更少的问题。

于 2015-03-29T13:50:35.287 回答
3

在 PHP 5 中,优点是性能会更好。它将查找名称为__constructfirst 的构造函数,如果找不到,它将查找名称为 的构造函数className。因此,如果它通过名称找到构造函数,__construct则不需要按名称搜索构造函数className

于 2008-10-20T06:00:04.227 回答
2

前向兼容性。为了向后兼容而留在语言中的遗留代码总是有可能在未来的版本中被删除。

于 2008-10-20T09:14:50.277 回答
1

如果有方法 __construct 和 SameAsClassName 方法,则 __construct 将被执行,SameAsClassName 方法将被跳过。

于 2013-12-06T06:35:54.493 回答
0

我认为主要原因是语言约定。你不需要强迫一种语言表现得像其他人一样。

我的意思是,例如,在 Objective-C 中,您可以在构造函数前加上 -init。您可以使用您的类名创建自己的构造函数,但为什么呢?有什么理由使用这个模式而不是语言约定吗?

于 2013-06-06T00:44:25.240 回答