svn: /phpdoc/zh/trunk/language/oop5/ decon.xml
[email protected] (Dai Jie) Sat, 28 Nov 2020 08:08:43 +0000
| Newsgroups | php.doc.zh |
|---|---|
| Message-ID | <[email protected]> |
daijie Sat, 28 Nov 2020 08:08:43 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=351721
Log:
Translate decon.xml
Changed paths:
U phpdoc/zh/trunk/language/oop5/decon.xml
svn-diffs-351721.txt
(text/x-diff, 10.8 KB)
Modified: phpdoc/zh/trunk/language/oop5/decon.xml
===================================================================
--- phpdoc/zh/trunk/language/oop5/decon.xml 2020-11-28 08:07:24 UTC (rev 351720)
+++ phpdoc/zh/trunk/language/oop5/decon.xml 2020-11-28 08:08:43 UTC (rev 351721)
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<!-- $Author$ -->
-<!-- EN-Revision: 329168 Maintainer: lm92 Status: ready -->
+<!-- EN-Revision: 351474 Maintainer: lm92 Status: ready -->
<sect1 xml:id="language.oop5.decon" xmlns="http://docbook.org/ns/docbook">
<title>构造函数和析构函数</title>
@@ -9,11 +9,10 @@
<title>构造函数</title>
<methodsynopsis xml:id="object.construct">
<type>void</type><methodname>__construct</methodname>
- <methodparam choice="opt"><type>mixed</type><parameter>args</parameter></methodparam>
- <methodparam choice="opt"><parameter>...</parameter></methodparam>
+ <methodparam rep="repeat"><type>mixed</type><parameter>values</parameter><initializer>""</initializer></methodparam>
</methodsynopsis>
<para>
- PHP 5 允行开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。
+ PHP 允许开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。
</para>
<note>
<simpara>
@@ -23,25 +22,25 @@
</simpara>
</note>
<example>
- <title>使用新标准的构造函数</title>
+ <title>继承中的构造函数</title>
<programlisting role="php">
<![CDATA[
<?php
class BaseClass {
- function __construct() {
- print "In BaseClass constructor\n";
- }
+ function __construct() {
+ print "In BaseClass constructor\n";
+ }
}
class SubClass extends BaseClass {
- function __construct() {
- parent::__construct();
- print "In SubClass constructor\n";
- }
+ function __construct() {
+ parent::__construct();
+ print "In SubClass constructor\n";
+ }
}
class OtherSubClass extends BaseClass {
- // inherits BaseClass's constructor
+ // 继承 BaseClass 的构造函数
}
// In BaseClass constructor
@@ -58,34 +57,173 @@
</programlisting>
</example>
<para>
- 为了实现向后兼容性,如果 PHP 5 在类中找不到 <link linkend="object.construct">__construct()</link>
- 函数并且也没有从父类继承一个的话,它就会尝试寻找旧式的构造函数,也就是和类同名的函数。因此唯一会产生兼容性问题的情况是:类中已有一个名为
- <function>__construct</function> 的方法却被用于其它用途时。
- </para>
- <para>
与其它方法不同,当 <link linkend="object.construct">__construct()</link>
被与父类 <link linkend="object.construct">__construct()</link>
具有不同参数的方法覆盖时,PHP 不会产生一个 <constant>E_STRICT</constant> 错误信息。
</para>
<para>
- 自 PHP 5.3.3 起,在命名空间中,与类名同名的方法不再作为构造函数。这一改变不影响不在命名空间中的类。
+ 自 PHP 5.3.3 起,在命名空间中,与类名同名的方法不再作为构造函数。不使用命名空间中的类则不受影响。
+ 构造函数是一个普通的方法,在对应对象实例化时自动被调用。
+ 因此可以定义任何数量的参数,可以是必选、可以有类型、可以有默认值。
+ 构造器的参数放在类名后的括号里调用。
</para>
<example>
- <title>Constructors in namespaced classes</title>
- <programlisting role="php">
+ <title>使用构造器参数</title>
+ <programlisting role="php">
<![CDATA[
<?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
+class Point {
+ protected int $x;
+ protected int $y;
+
+ public function __construct(int $x, int $y = 0) {
+ $this->x = $x;
+ $this->y = $y;
}
}
+
+// 两个参数都传入
+$p1 = new Point(4, 5);
+// 仅传入必填的参数。 $y 会默认取值 0。
+$p2 = new Point(4);
+// 使用命名参数(PHP 8.0 起):
+$p3 = new Point(y: 5, x: 4);
?>
]]>
- </programlisting>
+ </programlisting>
</example>
+ <para>
+ 如果一个类没有构造函数,以及构造函数的参数不是必填项时,括号就可以省略。
+ </para>
+ <sect3>
+ <title>旧式风格的构造器</title>
+ <para>
+ PHP 8.0.0 之前,全局命名空间内的类如果有一个同名的方法,则会解析为旧式风格的构造器。
+ 虽然函数能被当作构造器,但该语法已被废弃,并会导致 <constant>E_DEPRECATED</constant> 错误。
+ 如果 <link linkend="object.construct">__construct()</link> 和同名方法同时存在时,
+ 会调用 <link linkend="object.construct">__construct()</link>。
+ </para>
+ <para>
+ 以下两种情况时,与类同名的方法不再有特殊意义:命名空间中的类、PHP 8.0.0 起的任何类。
+ </para>
+ <para>新代码中要使用 <link linkend="object.construct">__construct()</link>。
+ </para>
+ </sect3>
+ <sect3 xml:id="language.oop5.decon.constructor.promotion">
+ <title>构造器属性提升</title>
+ <para>
+ PHP 8.0.0 起,构造器的参数也可以相应提升为类的属性。
+ 构造器的参数赋值给类属性的行为很普遍,否则无法操作。
+ 而构造器提升的功能则为这种场景提供了便利。
+ 因此上面的例子可以用以下方式重写:
+ </para>
+ <example>
+ <title>使用构造器属性提升</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+class Point {
+ public function __construct(protected int $x, protected int $y = 0) {
+ }
+}
+]]>
+ </programlisting>
+ </example>
+ <para>
+ 当构造器参数带访问控制(visibility modifier)时,PHP 会同时把它当作对象属性和构造器参数,
+ 并赋值到属性。
+ 构造器可以是空的,或者包含其他语句。
+ 参数值赋值到相应属性后执行正文中额外的代码语句。
+ </para>
+ <para>
+ 并非所有参数都需要提升。可以混合提升或不提升参数作为属性,也不需要按顺序。
+ 提升后的参数不影响构造器内代码调用。
+ </para>
+ <note>
+ <para>
+ 对象属性的类型不能为 <type>callable</type> 以避免为引擎带来混淆。
+ 因此提升的参数也不能是 <type>callable</type>。
+ 其他任意 <link linkend="language.types.declarations">类型声明</link> 是允许的。
+ </para>
+ </note>
+ <note>
+ <para>
+ <!-- This should be linked once attributes are documented. -->
+ 放在构造器提升参数里的属性会同时复制为属性和参数。
+ </para>
+ </note>
+ </sect3>
+ <sect3 xml:id="language.oop5.decon.constructor.static">
+ <title>Static 创造方法</title>
+ <para>
+ 在 PHP 中每个 class 只能有一个构造器。
+ 然而有些情况下,需要用不同的输入实现不同的方式构造对象。
+ 这种情况下推荐使用 static 方法包装构造。
+ </para>
+ <example>
+ <title>使用 static 创造方法</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+class Product {
+
+ private ?int $id;
+ private ?string $name;
+
+ private function __construct(?int $id = null, ?string $name = null) {
+ $this->id = $id;
+ $this->name = $name;
+ }
+
+ public static function fromBasicData(int $id, string $name): static {
+ $new = new static($id, $name);
+ return $new;
+ }
+
+ public static function fromJson(string $json): static {
+ $data = json_decode($json);
+ return new static($data['id'], $data['name']);
+ }
+
+ public static function fromXml(string $xml): static {
+ // 此处放置自己的代码逻辑
+ $data = convert_xml_to_array($xml);
+ $new = new static();
+ $new->id = $data['id'];
+ $new->name = $data['name'];
+ return $new;
+ }
+}
+
+$p1 = Product::fromBasicData(5, 'Widget');
+$p2 = Product::fromJson($some_json_string);
+$p3 = Product::fromXml($some_xml_string);
+]]>
+ </programlisting>
+ </example>
+ <para>
+ 可以设置构造器为 private 或 protected,防止自行额外调用。
+ 这时只有 static 方法可以实例化一个类。
+ 由于它们位于同一个定义的 class 因此可以访问私有方法,也不需要在同一个对象实例中。
+ 当然构造器不一定要设置为 private,是否合理取决于实际情况。
+ </para>
+ <para>
+ 三个 static 方法展示了对象以不同方式的实例化方式。
+ </para>
+ <simplelist>
+ <member><code>fromBasicData()</code> takes the exact parameters that are needed, then creates the
+ object by calling the constructor and returning the result.</member>
+ <member><code>fromJson()</code> accepts a JSON string and does some pre-processing on it itself
+ to convert it into the format desired by the constructor. It then returns the new object.</member>
+ <member><code>fromXml()</code> accepts an XML string, preprocesses it, and then creates a bare
+ object. The constructor is still called, but as all of the parameters are optional the method
+ skips them. It then assigns values to the object properties directly before returning the result.</member>
+ </simplelist>
+ <para>
+ 在以上三个例子中,<code>static</code> 关键词会被翻译成代码所在类的类名。
+ 这个例子中是 <code>Product</code>。
+ </para>
+ </sect3>
</sect2>
<sect2 xml:id="language.oop5.decon.destructor">
@@ -100,24 +238,25 @@
</para>
<example>
<title>析构函数示例</title>
- <programlisting role="php">
+ <programlisting role="php">
<![CDATA[
<?php
-class MyDestructableClass {
- function __construct() {
- print "In constructor\n";
- $this->name = "MyDestructableClass";
- }
- function __destruct() {
- print "Destroying " . $this->name . "\n";
- }
+class MyDestructableClass
+{
+ function __construct() {
+ print "In constructor\n";
+ }
+
+ function __destruct() {
+ print "Destroying " . __CLASS__ . "\n";
+ }
}
$obj = new MyDestructableClass();
-?>
+
]]>
- </programlisting>
+ </programlisting>
</example>
<para>
和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用
@@ -163,3 +302,4 @@
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
+