使用__construct()
代替PHP中构造函数的类名是否有任何优势?
示例(__construct
):
class Foo {
function __construct(){
//do stuff
}
}
示例(已命名):
class Foo {
function Foo(){
//do stuff
}
}
从PHP 5开始,可以使用__construct
方法(第一个例子)。
从PHP版本4到版本7,可以使用与类相同的方法作为构造函数(第二个示例)。
答案 0 :(得分:69)
我同意Gizmo,其优点是,如果重命名课程,则无需重命名。 DRY。
同样,如果你有一个子课,你可以打电话
parent::__construct()
调用父构造函数。如果在轨道的下方更改了子类继承的类,则不必将构造调用更改为父级。
这似乎是一件小事,但是缺少将构造函数调用名称更改为父类可能会产生微妙(而不是那么微妙)的错误。
例如,如果您将一个类插入到heirachy中,但忘记更改构造函数调用,则可以开始调用祖父母而不是父母的构造函数。这通常会导致可能难以察觉的不良结果。
另请注意
从PHP 5.3.3开始,与命名空间类名的最后一个元素同名的方法将不再被视为构造函数。此更改不会影响非命名空间的类。
答案 1 :(得分:20)
__construct
。这是你现在应该这样做的方式。不过,我本身并不知道的优点。
从PHP手册:
为了向后兼容,如果PHP 5找不到给定类的__construct()函数,它将按类的名称搜索旧式构造函数。实际上,这意味着唯一具有兼容性问题的情况是该类是否有一个名为__construct()的方法,该方法用于不同的语义
如果您使用的是PHP5,我建议您使用__construct
以避免让PHP在其他地方使用。
答案 2 :(得分:15)
我在__construct中看到的主要优点是,如果更改了类名,则无需重命名构造函数。
答案 3 :(得分:10)
今天,接受的答案已经过时了。
重命名类是不好的做法:每次升级到更新版本时,都必须记住重命名的内容和位置。有时候(比如使用Reflection或复杂的依赖结构),没有彻底的重构就不可能。这是你要避免的accidental complexity。这就是为什么名称空间被引入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();当您重命名该类时,您需要记住您使用Reflection的位置,并检查您的应用中getName()
结果是否仍然一致。你需要记住的东西越多,忘记的东西就越容易导致应用程序出现错误。
父母无法控制世界上依赖于他们的所有课程。如果启用了allow_url_include,则其他某些Web可能正在使用您服务器中的类,如果重命名某个类,则可能会崩溃。在上面提到的编译语言中更糟糕的是:可以将库复制并捆绑在其他代码中。
没有理由重命名课程:
在命名空间中的PHP类中,无论如何都应该避免使用相同名称的方法:直观地说它应该产生一个创建类的对象;如果它做了别的什么,为什么要给它相同的名字?它应该是一个构造函数而不是别的。主要问题是这种方法的行为取决于名称空间的使用。
PHP中的__construct构造函数没有问题。但改变命名的构造函数并不是最聪明的想法。
答案 4 :(得分:7)
使用__contruct()
代替ClassName()
的最大好处是扩展类时。调用parent::__construct()
而不是parent::ClassName()
要容易得多,因为它可以在类之间重复使用,并且可以轻松更改父级。
答案 5 :(得分:7)
在您的示例中,Foo::Foo
有时被称为PHP 4或旧式构造函数,因为它来自PHP 4时代:
class Foo {
// PHP 4 constructor
function Foo(){
//do stuff
}
}
PHP 7中的PHP 4 constructors will be deprecated but not removed。在PHP 8的任何情况下,它们将不再被视为构造函数。未来的兼容性绝对是不使用此功能的一个重要原因。
答案 6 :(得分:3)
在PHP 5中,优势在于性能会更好。它将首先查找名称为__construct
的构造函数,如果找不到,它将查找名称为className
的构造函数。因此,如果它找到名称为__construct
的构造函数,则不需要按名称className
搜索构造函数。
答案 7 :(得分:3)
自问这个问题以来已经过了几年了,但我想我还是要回答这个问题,因为事情已经发生了变化,对于未来的读者,我希望保持信息的最新状态!
因此在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
同名的方法,你也不会在php-7中得到__construct()
。
你也可以在这里看到:
当存在与该类名称相同的方法以及__construct时,PHP 7 也将停止发出E_STRICT 。
因此我建议您使用__construct()
,因为将来您的问题会更少。
答案 8 :(得分:2)
向前兼容性。为了向后兼容而留下的遗留代码总是有可能在将来的版本中删除。
答案 9 :(得分:1)
如果有方法__construct和SameAsClassName方法,那么将执行__construct,将跳过SameAsClassName方法。
答案 10 :(得分:0)
我认为主要原因是语言惯例。 您不需要强迫语言像其他人一样行事。
我的意思是,在Objective-C中,您可以使用-init为构造函数添加前缀。您可以使用您的类名创建自己的构造函数,但为什么?是否有理由使用此架构而不是语言约定?