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