com doc/zh: sync to en: oop 相关新 特性: .editorconfig language/functions. xml language/oop5/basic.xml

[email protected] (Bole Chen) Tue, 26 Jan 2021 02:55:14 +0000
Newsgroups php.doc.zh
Message-ID <[email protected]>
Commit:    6b35592a90301c4fff2093118d9024f5c50db664
Author:    Bole Chen <[email protected]>         Tue, 26 Jan 2021 10:55:14 +0800
Parents:   3042047601cab525c8c4a06ba11def7da79bb973
Branches:  master

Link:       http://git.php.net/?p=doc/zh.git;a=commitdiff;h=6b35592a90301c4fff2093118d9024f5c50db664

Log:
sync to en: oop 相关新特性

Changed paths:
  A  .editorconfig
  M  language/functions.xml
  M  language/oop5/basic.xml
diff_6b35592a90301c4fff2093118d9024f5c50db664.txt (text/plain, 45.2 KB)
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..ae8c5287
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,7 @@
+# EditorConfig is awesome: https://EditorConfig.org
+
+root = true
+
+[*.xml]
+indent_style = space
+indent_size = 1
diff --git a/language/functions.xml b/language/functions.xml
index 2cd3e8c4..990ff875 100644
--- a/language/functions.xml
+++ b/language/functions.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- $Revision$ -->
 <!-- $Author$ -->
-<!-- EN-Revision: 574f492ae951e820d36bc6d9273f9da90ba46ef7 Maintainer: avenger Status: ready -->
+<!-- EN-Revision: 4f04bd50ed71039b89e2b9a5aba7e53e74cac4c6 Maintainer: avenger Status: ready -->
 <!-- CREDITS: Gregory, dallas -->
 <chapter xml:id="language.functions" xmlns="http://docbook.org/ns/docbook">
   <title>函数</title>
@@ -30,8 +30,8 @@ function foo($arg_1, $arg_2, /* ..., */ $arg_n)
    </para>
 
    <simpara>
-    任何有效的 PHP 代码都有可能出现在函数内部,甚至包括其它函数和 <link
-    linkend="language.oop5.basic.class">类</link>定义。
+    任何有效的 PHP 代码都有可能出现在函数内部,甚至包括其它函数和
+    <link linkend="language.oop5.basic.class">类</link> 定义。
    </simpara>
    <para>
     函数名和 PHP 中的其它标识符命名规则相同。有效的函数名以字母或下划线打头,后面跟字母,数字或下划线。可以用正则表达式表示为:
@@ -65,7 +65,7 @@ if ($makefoo) {
   }
 }
 
-/* 现在可以安全调用函数 foo()了,
+/* 现在可以安全调用函数 foo()
    因为 $makefoo 值为真 */
 
 if ($makefoo) foo();
@@ -80,12 +80,6 @@ function bar()
      </programlisting>
     </example>
    </para>
-   
-   
-   
-   
-   
-   
    <para>
     <example>
      <title>函数中的函数</title>
@@ -100,12 +94,12 @@ function foo()
   }
 }
 
-/* 现在还不能调用bar()函数,因为它还不存在 */
+/* 现在还不能调用 bar() 函数,因为它还不存在 */
 
 foo();
 
-/* 现在可以调用bar()函数了,因为foo()函数
-   的执行使得bar()函数变为已定义的函数 */
+/* 现在可以调用 bar() 函数了,因为 foo() 函数
+   的执行使得 bar() 函数变为已定义的函数 */
 
 bar();
 
@@ -126,20 +120,12 @@ bar();
      的 ASCII 函数名是大小写无关的,不过在调用函数的时候,使用其在定义时相同的形式是个好习惯。
     </simpara>
    </note>
-   
-   
-   
-      
    <simpara>
     PHP 的函数支持 <link linkend="functions.variable-arg-list">可变数量的参数</link> 和
     <link linkend="functions.arguments.default">默认参数</link>。参见
     <function>func_num_args</function>,<function>func_get_arg</function> 和 <function>func_get_args</function>。
    </simpara>
 
-   
-   
-   
-
    <para>
     在 PHP 中可以调用递归函数。
     <example>
@@ -160,14 +146,13 @@ function recursion($a)
     </example>
    <note>
     <simpara>
-    但是要避免递归函数/方法调用超过
-    100-200 层,因为可能会使堆栈崩溃从而使当前脚本终止。
+    但是要避免递归函数/方法调用超过 100-200 层,因为可能会使堆栈崩溃从而使当前脚本终止。
     无限递归可视为编程错误。
     </simpara>
    </note>
    </para>
-  </sect1>
 
+  </sect1>
 
   <sect1 xml:id="functions.arguments">
    <title>函数的参数</title>
@@ -175,10 +160,7 @@ function recursion($a)
    <simpara>
     通过参数列表可以传递信息到函数,即以逗号作为分隔符的表达式列表。参数是从左向右求值的。
    </simpara>
-   
-   
-   
-   
+
    <para>
     PHP 支持按值传递参数(默认),<link
     linkend="functions.arguments.by-reference">通过引用传递参数</link> 以及 <link
@@ -200,12 +182,11 @@ function takes_array($input)
      </programlisting>
     </example>
    </para>
-
    <para>
     从 PHP 8.0.0 开始,函数参数列表可以包含一个尾部的逗号,这个逗号将被忽略。这在参数列表较长或包含较长的变量名的情况下特别有用,这样可以方便地垂直列出参数。
    </para>
    <example>
-    <title>Function Argument List with trailing Comma</title>
+    <title>函数参数使用尾部逗号</title>
     <programlisting role="php">
 <![CDATA[
 <?php
@@ -223,7 +204,28 @@ function takes_many_args(
 ]]>
     </programlisting>
    </example>
+   <para>
+    As of PHP 8.0.0, passing mandatory arguments after optional arguments
+    is deprecated. This can generally be resolved by dropping the default value.
+    One exception to this rule are arguments of the form
+    <code>Type $param = null</code>, where the &null; default makes the type implicitly
+    nullable. This usage remains allowed, though it is recommended to use an
+    explicit nullable type instead.
+   </para>
+   <example>
+    <title>Passing optional arguments after mandatory arguments</title>
+    <programlisting role="php">
+<![CDATA[
+<?php
+function foo($a = [], $b) {} // 之前
+function foo($a, $b) {}      // 之后
 
+function bar(A $a = null, $b) {} // 同时可用
+function bar(?A $a, $b) {}       // 官方推荐的写法
+?>
+]]>
+    </programlisting>
+   </example>
 
    <sect2 xml:id="functions.arguments.by-reference">
     <title>通过引用传递参数</title>
@@ -233,7 +235,7 @@ function takes_many_args(
     </simpara>
     <para>
      如果想要函数的一个参数总是通过引用传递,可以在函数定义中该参数的前面加上符号 &amp;:
-    </para>    
+    </para>
     <para>
      <example>
       <title>用引用传递函数参数</title>
@@ -253,10 +255,6 @@ echo $str;    // outputs 'This is a string, and something extra.'
      </example>
     </para>
    </sect2>
-
-   
-   
-   
    <sect2 xml:id="functions.arguments.default">
     <title>默认参数的值</title>
 
@@ -310,15 +308,12 @@ echo makecoffee(array("cappuccino", "lavazza"), "teapot");
       </programlisting>
      </example>
     </para>
-
     <simpara>
      默认值必须是常量表达式,不能是诸如变量,类成员,或者函数调用等。
     </simpara>
     <para>
      注意当使用默认参数时,任何默认参数必须放在任何非默认参数的右侧;否则,函数将不会按照预期的情况工作。考虑下面的代码片断:
     </para>
-    
-    
     <para>
      <example>
       <title>函数默认参数的不正确用法</title>
@@ -337,7 +332,7 @@ echo makeyogurt("raspberry");   // won't work as expected
       &example.outputs;
       <screen>
 <![CDATA[
-Warning: Missing argument 2 in call to makeyogurt() in 
+Warning: Missing argument 2 in call to makeyogurt() in
 /usr/local/etc/httpd/htdocs/phptest/functest.html on line 41
 Making a bowl of raspberry .
 ]]>
@@ -377,13 +372,9 @@ Making a bowl of acidophilus raspberry.
     </note>
    </sect2>
 
-
-   
-   
    <sect2 xml:id="functions.variable-arg-list">
     <title>可变数量的参数列表</title>
 
-
     <simpara>
      PHP 在用户自定义函数中支持可变数量的参数列表。由
      <literal>...</literal> 语法实现。
@@ -399,16 +390,13 @@ Making a bowl of acidophilus raspberry.
      </simpara>
     </note>
 
-     <para>
-      包含 <literal>...</literal>
-      的参数,会转换为指定参数变量的一个数组,见以下示例:
-
+    <para>
+     包含 <literal>...</literal>
+     的参数,会转换为指定参数变量的一个数组,见以下示例:
 
-      
-      
-      <example>
-       <title>使用 <literal>...</literal> 来访问变量参数</title>
-       <programlisting role="php">
+     <example>
+      <title>使用 <literal>...</literal> 来访问变量参数</title>
+      <programlisting role="php">
 <![CDATA[
 <?php
 function sum(...$numbers) {
@@ -422,24 +410,24 @@ function sum(...$numbers) {
 echo sum(1, 2, 3, 4);
 ?>
 ]]>
-       </programlisting>
-       &example.outputs;
-       <screen>
+      </programlisting>
+      &example.outputs;
+      <screen>
 <![CDATA[
 10
 ]]>
-       </screen>
-      </example>
-     </para>
+      </screen>
+     </example>
+    </para>
 
-     <para>
-      也可以使用 <literal>...</literal> 语法来传递 <type>array</type> 或
-      <classname>Traversable</classname> 做为参数到函数中:
+    <para>
+    也可以使用 <literal>...</literal> 语法来传递 <type>array</type> 或
+     <classname>Traversable</classname> 做为参数到函数中:
 
 
-      <example>
-       <title>使用 <literal>...</literal> 来传递参数</title>
-       <programlisting role="php">
+     <example>
+      <title>使用 <literal>...</literal> 来传递参数</title>
+      <programlisting role="php">
 <![CDATA[
 <?php
 function add($a, $b) {
@@ -452,16 +440,16 @@ $a = [1, 2];
 echo add(...$a);
 ?>
 ]]>
-       </programlisting>
-       &example.outputs;
-       <screen>
+      </programlisting>
+      &example.outputs;
+      <screen>
 <![CDATA[
 3
 3
 ]]>
-       </screen>
-      </example>
-     </para>
+      </screen>
+     </example>
+    </para>
 
     <para>
      你可以在
@@ -477,8 +465,8 @@ echo add(...$a);
 
 
      <example>
-       <title>输入提示的变量参数</title>
-       <programlisting role="php">
+      <title>输入提示的变量参数</title>
+      <programlisting role="php">
 <![CDATA[
 <?php
 function total_intervals($unit, DateInterval ...$intervals) {
@@ -497,23 +485,22 @@ echo total_intervals('d', $a, $b).' days';
 echo total_intervals('d', null);
 ?>
 ]]>
-       </programlisting>
-       &example.outputs;
-       <screen>
+      </programlisting>
+      &example.outputs;
+      <screen>
 <![CDATA[
 3 days
 Catchable fatal error: Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in - on line 14 and defined in - on line 2
 ]]>
-       </screen>
-      </example>
-     </para>
+      </screen>
+     </example>
+    </para>
 
-     <para>
+    <para>
       最后,你还可以给参数传递
-      <link linkend="functions.arguments.by-reference">引用变量</link>,通过在
+     <link linkend="functions.arguments.by-reference">引用变量</link>,通过在
       <literal>...</literal> 前加上一个 (<literal>&amp;</literal>) 符号来实现。
-     </para>
-
+    </para>
 
     <sect3 xml:id="functions.variable-arg-list.old">
      <title>旧版本的 PHP</title>
@@ -555,8 +542,112 @@ echo sum(1, 2, 3, 4);
     </sect3>
 
    </sect2>
-  </sect1>
 
+   <sect2 xml:id="functions.named-arguments">
+    <title>Named Arguments</title>
+
+    <para>
+     PHP 8.0.0 introduced named arguments as an extension of the existing
+     positional parameters. Named arguments allow passing arguments to a
+     function based on the parameter name, rather than the parameter position.
+     This makes the meaning of the argument self-documenting, makes the
+     arguments order-independent and allows skipping default values arbitrarily.
+    </para>
+
+    <para>
+     Named arguments are passed by prefixing the value with the parameter name
+     followed by a colon. Using reserved keywords as parameter names is allowed.
+     The parameter name must be an identifier, specifying dynamically
+     is not allowed.
+    </para>
+
+    <example>
+     <title>Named argument syntax</title>
+     <programlisting role="php">
+      <![CDATA[
+<?php
+myFunction(paramName: $value);
+array_foobar(array: $value);
+
+// NOT supported.
+function_name($variableStoringParamName: $value);
+?>
+]]>
+     </programlisting>
+    </example>
+
+    <example>
+     <title>Positional arguments versus named arguments</title>
+     <programlisting role="php">
+      <![CDATA[
+<?php
+// Using positional arguments:
+array_fill(0, 100, 50);
+
+// Using named arguments:
+array_fill(start_index: 0, count: 100, value: 50);
+?>
+]]>
+     </programlisting>
+    </example>
+
+    <para>
+     The order in which the named arguments are passed does not matter.
+    </para>
+
+    <example>
+     <title>Same example as above with a different order of parameters</title>
+     <programlisting role="php">
+      <![CDATA[
+<?php
+array_fill(value: 50, num: 100, start_index: 0);
+?>
+]]>
+     </programlisting>
+    </example>
+
+    <para>
+     Named arguments can be combined with positional arguments. In this case,
+     the named arguments must come after the positional arguments.
+     It is also possible to specify only some of the optional arguments of a
+     function, regardless of their order.
+    </para>
+
+    <example>
+     <title>Combining named arguments with positional arguments</title>
+     <programlisting role="php">
+      <![CDATA[
+<?php
+htmlspecialchars($string, double_encode: false);
+// Same as
+htmlspecialchars($string, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
+?>
+]]>
+     </programlisting>
+    </example>
+
+    <para>
+     Passing the same parameter multiple times results in an Error exception.
+    </para>
+
+    <example>
+     <title>Error exception when passing the same parameter multiple times</title>
+     <programlisting role="php">
+      <![CDATA[
+<?php
+function foo($param) { ... }
+
+foo(param: 1, param: 2);
+// Error: Named parameter $param overwrites previous argument
+foo(1, param: 2);
+// Error: Named parameter $param overwrites previous argument
+?>
+]]>
+     </programlisting>
+    </example>
+
+   </sect2>
+  </sect1>
 
   <sect1 xml:id="functions.returning-values">
    <title>返回值</title>
@@ -571,14 +662,10 @@ echo sum(1, 2, 3, 4);
      <function>return</function>,则返回值为 &null;。
     </para>
    </note>
-   
-   
 
-   
-   
    <sect2>
-     <title>return 的使用</title>
-     <para>
+    <title>return 的使用</title>
+    <para>
      <example>
      <title><function>return</function> 的使用</title>
      <programlisting role="php">
@@ -591,17 +678,17 @@ function square($num)
 echo square(4);   // outputs '16'.
 ?>
 ]]>
-     </programlisting>
+      </programlisting>
      </example>
-   </para>
+    </para>
 
-   <para>
-    函数不能返回多个值,但可以通过返回一个数组来得到类似的效果。
-   </para>
-   <para>
-    <example>
-     <title>返回一个数组以得到多个返回值</title>
-     <programlisting role="php">
+    <para>
+     函数不能返回多个值,但可以通过返回一个数组来得到类似的效果。
+    </para>
+    <para>
+     <example>
+      <title>返回一个数组以得到多个返回值</title>
+      <programlisting role="php">
 <![CDATA[
 <?php
 function small_numbers()
@@ -611,19 +698,16 @@ function small_numbers()
 list ($zero, $one, $two) = small_numbers();
 ?>
 ]]>
-     </programlisting>
+      </programlisting>
      </example>
-   </para>
-   <para>
-    从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用运算符 &amp;:
-   </para>
-   <para>
-
-    
-    
-    <example>
-     <title>从函数返回一个引用</title>
-     <programlisting role="php">
+    </para>
+    <para>
+     从函数返回一个引用,必须在函数声明和指派返回值给一个变量时都使用引用运算符 &amp;:
+    </para>
+    <para>
+     <example>
+      <title>从函数返回一个引用</title>
+      <programlisting role="php">
 <![CDATA[
 <?php
 function &returns_reference()
@@ -634,15 +718,14 @@ function &returns_reference()
 $newref =& returns_reference();
 ?>
 ]]>
-     </programlisting>
+      </programlisting>
      </example>
-   </para>
-   <simpara>
+    </para>
+    <simpara>
     有关引用的更多信息, 请查看 <link linkend="language.references">引用的解释</link>。
    </simpara>
-   </sect2> 
-  </sect1>  
-  
+   </sect2>
+  </sect1>
 
   <sect1 xml:id="functions.variable-functions">
    <title>可变函数</title>
@@ -650,7 +733,7 @@ $newref =& returns_reference();
    <para>
     PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP
     将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
-    </para>
+   </para>
    <para>
     可变函数不能用于例如
     <function>echo</function>,<function>print</function>,<function>unset</function>,<function>isset</function>,<function>empty</function>,<function>include</function>,<function>require</function>
@@ -666,7 +749,8 @@ function foo() {
     echo "In foo()<br />\n";
 }
 
-function bar($arg = '') {
+function bar($arg = '')
+{
     echo "In bar(); argument was '$arg'.<br />\n";
 }
 
@@ -712,14 +796,13 @@ class Foo
 
 $foo = new Foo();
 $funcname = "Variable";
-$foo->$funcname();   // This calls $foo->Variable()
+$foo->$funcname();  // This calls $foo->Variable()
 
 ?>
 ]]>
      </programlisting>
     </example>
    </para>
-
    <para>
     当调用静态方法时,函数调用要比静态属性优先:
     <example>
@@ -775,7 +858,7 @@ $func(); // prints "bar"
     </example>
    </para>
 
-  <sect2 role="seealso">
+   <sect2 role="seealso">
     &reftitle.seealso;
     <para>
      <simplelist>
@@ -789,38 +872,37 @@ $func(); // prints "bar"
   </sect1>
 
   <sect1 xml:id="functions.internal">
-     <title>内部(内置)函数</title>
-
-     <para>
-      PHP 有很多标准的函数和结构。还有一些函数需要和特定地 PHP
-      扩展模块一起编译,否则在使用它们的时候就会得到一个致命的“未定义函数”错误。例如,要使用
-      <link linkend="ref.image">image</link> 函数中的
-      <function>imagecreatetruecolor</function>,需要在编译 PHP 的时候加上
-      <productname>GD</productname> 的支持。或者,要使用
-      <function>mysqli_connect</function> 函数,就需要在编译 PHP 的时候加上
-      <link linkend="book.mysqli">MySQLi</link> 支持。有很多核心函数已包含在每个版本的
-      PHP 中如<link linkend="ref.strings">字符串</link>和<link
-      linkend="ref.var">变量</link>函数。调用
-      <function>phpinfo</function> 或者 <function>get_loaded_extensions</function>
-      可以得知 PHP 加载了那些扩展库。同时还应该注意,很多扩展库默认就是有效的。PHP
-      手册按照不同的扩展库组织了它们的文档。请参阅<link
-      linkend="configuration">配置</link>,<link
-      linkend="install">安装</link>以及各自的扩展库章节以获取有关如何设置 PHP 的信息。
-     </para>
-     <para>
-      手册中<link
-      linkend="about.prototypes">如何阅读函数原型</link>讲解了如何阅读和理解一个函数的原型。确认一个函数将返回什么,或者函数是否直接作用于传递的参数是很重要的。例如,<function>str_replace</function>
-      函数将返回修改过的字符串,而 <function>usort</function>
-      却直接作用于传递的参数变量本身。手册中,每一个函数的页面中都有关于函数参数、行为改变、成功与否的返回值以及使用条件等信息。了解这些重要的(常常是细微的)差别是编写正确的
-      PHP 代码的关键。
-     </para>
+  <title>内部(内置)函数</title>
+
+  <para>
+   PHP 有很多标准的函数和结构。还有一些函数需要和特定地 PHP
+   扩展模块一起编译,否则在使用它们的时候就会得到一个致命的“未定义函数”错误。例如,要使用
+   <link linkend="ref.image">image</link> 函数中的
+   <function>imagecreatetruecolor</function>,需要在编译 PHP 的时候加上
+   <productname>GD</productname> 的支持。或者,要使用
+   <function>mysqli_connect</function> 函数,就需要在编译 PHP 的时候加上
+   <link linkend="book.mysqli">MySQLi</link> 支持。有很多核心函数已包含在每个版本的
+   PHP 中如<link linkend="ref.strings">字符串</link>和<link
+   linkend="ref.var">变量</link>函数。调用
+   <function>phpinfo</function> 或者 <function>get_loaded_extensions</function>
+   可以得知 PHP 加载了那些扩展库。同时还应该注意,很多扩展库默认就是有效的。PHP
+   手册按照不同的扩展库组织了它们的文档。请参阅<link linkend="configuration">配置</link>,<link
+   linkend="install">安装</link>以及各自的扩展库章节以获取有关如何设置 PHP 的信息。
+  </para>
+  <para>
+   手册中<link
+   linkend="about.prototypes">如何阅读函数原型</link>讲解了如何阅读和理解一个函数的原型。确认一个函数将返回什么,或者函数是否直接作用于传递的参数是很重要的。例如,<function>str_replace</function>
+   函数将返回修改过的字符串,而 <function>usort</function>
+   却直接作用于传递的参数变量本身。手册中,每一个函数的页面中都有关于函数参数、行为改变、成功与否的返回值以及使用条件等信息。了解这些重要的(常常是细微的)差别是编写正确的
+   PHP 代码的关键。
+   </para>
    <note>
     <simpara>
      如果传递给函数的参数类型与实际的类型不一致,例如将一个 <type>array</type>
      传递给一个 <type>string</type> 类型的变量,那么函数的返回值是不确定的。在这种情况下,通常函数会返回
      &null;。但这仅仅是一个惯例,并不一定如此。
     </simpara>
-   </note>    
+   </note>
 
    <sect2 role="seealso">
     &reftitle.seealso;
@@ -833,9 +915,8 @@ $func(); // prints "bar"
      </simplelist>
     </para>
    </sect2>
-    </sect1>
+  </sect1>
 
-  
   <sect1 xml:id="functions.anonymous">
    <title>匿名函数</title>
 
@@ -843,7 +924,6 @@ $func(); // prints "bar"
     匿名函数(Anonymous functions),也叫闭包函数(<literal>closures</literal>),允许
     临时创建一个没有指定名称的函数。最经常用作回调函数 <type>callable</type>参数的值。当然,也有其它应用的情况。
    </simpara>
-     
    <simpara>
     匿名函数目前是通过 <link linkend="class.closure">
     <classname>Closure</classname></link> 类来实现的。
@@ -885,10 +965,10 @@ $greet('PHP');
 ]]>
     </programlisting>
    </example>
-   
+
    <simpara>
     闭包可以从父作用域中继承变量。
-   任何此类变量都应该用 <literal>use</literal> 语言结构传递进去。 
+   任何此类变量都应该用 <literal>use</literal> 语言结构传递进去。
     PHP 7.1 起,不能传入此类变量:  &link.superglobals;、 <varname>$this</varname> 或者和参数重名。
    </simpara>
 
@@ -903,18 +983,18 @@ $message = 'hello';
 $example = function () {
     var_dump($message);
 };
-echo $example();
+$example();
 
 // 继承 $message
 $example = function () use ($message) {
     var_dump($message);
 };
-echo $example();
+$example();
 
 // Inherited variable's value is from when the function
 // is defined, not when called
 $message = 'world';
-echo $example();
+$example();
 
 // Reset message
 $message = 'hello';
@@ -923,12 +1003,12 @@ $message = 'hello';
 $example = function () use (&$message) {
     var_dump($message);
 };
-echo $example();
+$example();
 
 // The changed value in the parent scope
 // is reflected inside the function call
 $message = 'world';
-echo $example();
+$example();
 
 // Closures can also accept regular arguments
 $example = function ($arg) use ($message) {
@@ -955,10 +1035,9 @@ string(11) "hello world"
    <para>
     从 PHP 8.0.0 开始,作用域继承的变量列表可能包含一个尾部的逗号,这个逗号将被忽略。
    </para>
-
   <simpara>
     这些变量都必须在函数或类的头部声明。
-    
+
     从父作用域中继承变量与使用全局变量是<emphasis>不同</emphasis>的。全局变量存在于一个全局的范围,无论当前在执行的是哪个函数。而
     闭包的父作用域是定义该闭包的函数(不一定是调用它的函数)。示例如下:
    </simpara>
@@ -977,23 +1056,23 @@ class Cart
     const PRICE_MILK    = 3.00;
     const PRICE_EGGS    = 6.95;
 
-    protected   $products = array();
-    
+    protected $products = array();
+
     public function add($product, $quantity)
     {
         $this->products[$product] = $quantity;
     }
-    
+
     public function getQuantity($product)
     {
         return isset($this->products[$product]) ? $this->products[$product] :
                FALSE;
     }
-    
+
     public function getTotal($tax)
     {
         $total = 0.00;
-        
+
         $callback =
             function ($quantity, $product) use ($tax, &$total)
             {
@@ -1001,9 +1080,9 @@ class Cart
                     strtoupper($product));
                 $total += ($pricePerItem * $quantity) * ($tax + 1.0);
             };
-        
+
         array_walk($this->products, $callback);
-        return round($total, 2);;
+        return round($total, 2);
     }
 }
 
@@ -1021,8 +1100,7 @@ print $my_cart->getTotal(0.05) . "\n";
 ]]>
     </programlisting>
    </example>
-     
-     
+
    <example>
     <title>自动绑定 <literal>$this</literal></title>
     <programlisting role="php">
@@ -1042,7 +1120,7 @@ class Test
 $object = new Test;
 $function = $object->testing();
 $function();
-    
+
 ?>
 ]]>
     </programlisting>
@@ -1054,13 +1132,14 @@ object(Test)#1 (0) {
 ]]>
     </screen>
    </example>
-   
+
    <para>
     当在类的上下文中声明时,当前的类会自动与之绑定,使得
     <literal>$this</literal> 在函数的作用域中可用。如果不需要当前类的自动绑定,可以使用
     <link linkend="functions.anonymous-functions.static">静态匿名函数</link> 替代。
    </para>
-     <sect2 xml:id="functions.anonymous-functions.static">
+
+   <sect2 xml:id="functions.anonymous-functions.static">
     <title>静态匿名函数</title>
     <para>
      匿名函数允许被定义为静态化。这样可以防止当前类自动绑定到它们身上,对象在运行时也可能不会被绑定到它们上面。
@@ -1122,7 +1201,7 @@ Warning: Cannot bind an instance to a static closure in %s on line %d
      </example>
     </para>
    </sect2>
-     
+
    <sect2 role="changelog">
     &reftitle.changelog;
     <para>
@@ -1161,7 +1240,6 @@ Warning: Cannot bind an instance to a static closure in %s on line %d
    </sect2>
 
   </sect1>
-
   <sect1 xml:id="functions.arrow">
    <title>箭头函数</title>
 
@@ -1197,7 +1275,7 @@ Warning: Cannot bind an instance to a static closure in %s on line %d
 <?php
 
 $y = 1;
- 
+
 $fn1 = fn($x) => $x + $y;
 // 相当于 using $y by value:
 $fn2 = function ($x) use ($y) {
@@ -1279,7 +1357,7 @@ var_export($x);  // 输出 1
      </programlisting>
     </example>
    </para>
-   
+
    <sect2 role="changelog">
     &reftitle.changelog;
     <para>
@@ -1336,4 +1414,3 @@ vim600: syn=xml fen fdm=syntax fdl=2 si
 vim: et tw=78 syn=sgml
 vi: ts=1 sw=1
 -->
-
diff --git a/language/oop5/basic.xml b/language/oop5/basic.xml
index 7ec735ce..c02eca95 100755
--- a/language/oop5/basic.xml
+++ b/language/oop5/basic.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- $Revision$ -->
 <!-- $Author$ -->
-<!-- EN-Revision: 0fe00e3574f5267948a29692e8daddaaeb275cee Maintainer: dallas Status: ready -->
+<!-- EN-Revision: 02f3bf57175c48abff767ad2c0961c6cfe58a39e Maintainer: avenger Status: ready -->
 <sect1 xml:id="language.oop5.basic" xmlns="http://docbook.org/ns/docbook">
  <title>基本概念</title>
 
@@ -13,10 +13,12 @@
   </para>
   <para>
    类名可以是任何非 PHP
-   <link linkend="reserved">保留字</link>的合法标签。一个合法类名以字母或下划线开头,后面跟着若干字母,数字或下划线。以正则表达式表示为:<literal>[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*</literal>。
+   <link linkend="reserved">保留字</link>
+      的合法标签。一个合法类名以字母或下划线开头,后面跟着若干字母,数字或下划线。以正则表达式表示为:
+      <code>^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>。
   </para>
   <para>
-   一个类可以包含有属于自己的<link
+   一个类可以包含有属于自己的 <link
    linkend="language.oop5.constants">常量</link>,<link
    linkend="language.oop5.properties">变量</link>(称为“属性”)以及函数(称为“方法”)。
   </para>
@@ -42,17 +44,17 @@ class SimpleClass
   <para>
    当一个方法在类定义内部被调用时,有一个可用的伪变量
    <varname>$this</varname>。<varname>$this</varname>
-   是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象<link
-   linkend="language.oop5.static">静态</link>调用时也可能是另一个对象)。
+   是一个到当前对象的引用。
   </para>
-  <para>
+  <warning>
+      <para>
+          以静态方式去调用一个静态方法,将会抛出一个
+          <classname>Error</classname>。
+          在 PHP 8.0.0 之前版本中,将会产生一个废弃通知,同时
+          <varname>$this</varname> 将会被声明为未定义。
+      </para>
    <example xml:id="language.oop5.basic.class.this">
-    <title><varname>$this</varname> 伪变量的示例</title>
-     <simpara>
-      We're assuming that error_reporting is disabled for this example;
-      otherwise the following code would trigger deprecated and strict notices,
-      respectively, depending on the PHP version.
-     </simpara>
+    <title>使用 <varname>$this</varname> 伪变量的示例</title>
     <programlisting role="php">
 <![CDATA[
 <?php
@@ -89,40 +91,58 @@ $b->bar();
 B::bar();
 ?>
 ]]>
-    </programlisting>
-     &example.outputs.5;
+     </programlisting>
+     &example.outputs.7;
      <screen>
 <![CDATA[
 $this is defined (A)
+
+Deprecated: Non-static method A::foo() should not be called statically in %s  on line 27
+$this is not defined.
+
+Deprecated: Non-static method A::foo() should not be called statically in %s  on line 20
 $this is not defined.
-$this is defined (B)
+
+Deprecated: Non-static method B::bar() should not be called statically in %s  on line 32
+
+Deprecated: Non-static method A::foo() should not be called statically in %s  on line 20
 $this is not defined.
 ]]>
      </screen>
-     &example.outputs.7;
+     &example.outputs.8;
      <screen>
 <![CDATA[
 $this is defined (A)
-$this is not defined.
-$this is not defined.
-$this is not defined.
+
+Fatal error: Uncaught Error: Non-static method A::foo() cannot be called statically in %s :27
+Stack trace:
+#0 {main}
+  thrown in %s  on line 27
 ]]>
      </screen>
-   </example>
-  </para>
- </sect2>
+    </example>
+   </warning>
+  </sect2>
 
  <sect2 xml:id="language.oop5.basic.new">
   <title>new</title>
   <para>
    要创建一个类的实例,必须使用 <literal>new</literal>
-   关键字。当创建新对象时该对象总是被赋值,除非该对象定义了<link
-   linkend="language.oop5.decon">构造函数</link>并且在出错时抛出了一个<link
+   关键字。当创建新对象时该对象总是被赋值,除非该对象定义了 <link
+   linkend="language.oop5.decon">构造函数</link> 并且在出错时抛出了一个 <link
    linkend="language.exceptions">异常</link>。类应在被实例化之前定义(某些情况下则必须这样)。
   </para>
   <para>
-   如果在 <literal>new</literal> 之后跟着的是一个包含有类名的字符串 <type>string</type>,则该类的一个实例被创建。如果该类属于一个命名空间,则必须使用其完整名称。
+   如果在 <literal>new</literal> 之后跟着的是一个包含有类名的字符串
+      <type>string</type>,则该类的一个实例被创建。如果该类属于一个命名空间,则必须使用其完整名称。
   </para>
+
+   <note>
+    <para>
+      如果没有参数要传递给类的构造函数,类名后的括号则可以省略掉。
+    </para>
+   </note>
+
   <example>
    <title>创建实例</title>
    <programlisting role="php">
@@ -131,8 +151,8 @@ $this is not defined.
 $instance = new SimpleClass();
 
 // 也可以这样做:
-$className = 'Foo';
-$instance = new $className(); // Foo()
+$className = 'SimpleClass';
+$instance = new $className(); // new SimpleClass()
 ?>
 ]]>
    </programlisting>
@@ -141,8 +161,8 @@ $instance = new $className(); // Foo()
    在类定义内部,可以用 <literal>new self</literal> 和 <literal>new parent</literal> 创建新对象。
   </para>
   <para>
-   当把一个对象已经创建的实例赋给一个新变量时,新变量会访问同一个实例,就和用该对象赋值一样。此行为和给函数传递入实例时一样。可以用<link
-   linkend="language.oop5.cloning">克隆</link>给一个已创建的对象建立一个新实例。
+      当把一个对象已经创建的实例赋给一个新变量时,新变量会访问同一个实例,就和用该对象赋值一样。此行为和给函数传递入实例时一样。可以用
+      <link linkend="language.oop5.cloning">克隆</link> 给一个已创建的对象建立一个新实例。
   </para>
    <example>
     <title>对象赋值</title>
@@ -178,7 +198,7 @@ object(SimpleClass)#1 (1) {
     </screen>
    </example>
   <para>
-   PHP 5.3.0 引进了两个新方法来创建一个对象的实例:
+      有几种方法可以创建一个对象的实例。
   </para>
   <example>
    <title>创建新对象</title>
@@ -207,19 +227,19 @@ $obj4 = Child::getNew();
 var_dump($obj4 instanceof Child);
 ?>
 ]]>
-   </programlisting>
-   &example.outputs;
-   <screen>
+    </programlisting>
+    &example.outputs;
+    <screen>
 <![CDATA[
 bool(true)
 bool(true)
 bool(true)
 ]]>
-   </screen>
-  </example>
-  
+    </screen>
+   </example>
+
    <para>
-    PHP 5.4.0 起,可以通过一个表达式来访问新创建对象的成员:
+    可以通过一个表达式来访问新创建对象的成员:
    </para>
    <example>
     <title>访问新创建对象的成员</title>
@@ -237,26 +257,28 @@ echo (new DateTime())->format('Y');
 ]]>
     </screen>
    </example>
- </sect2>
-  
+
+   <note>
+    <simpara>
+     在 PHP 7.1 之前,如果类没有定义构造函数,则不对参数进行执行。
+    </simpara>
+   </note>
+  </sect2>
+
   <sect2 xml:id="language.oop5.basic.properties-methods">
-   <title>Properties and methods</title>
+   <title>属性和方法</title>
    <para>
-    Class properties and methods live in separate "namespaces", so it is
-    possible to have a property and a method with the same name. Referring to
-    both a property and a method has the same notation, and whether a property
-    will be accessed or a method will be called, solely depends on the context,
-    i.e. whether the usage is a variable access or a function call.
+    类的属性和方法存在于不同的“命名空间”中,这意味着同一个类的属性和方法可以使用同样的名字。在类中访问属性和调用方法使用同样的操作符,具体是访问一个属性还是调用一个方法,取决于你的上下文,即用法是变量访问还是函数调用。
    </para>
    <example>
-    <title>Property access vs. method call</title>
+    <title>访问类属性 vs. 调用类方法</title>
     <programlisting role="php">
 <![CDATA[
 <?php
 class Foo
 {
     public $bar = 'property';
-    
+
     public function bar() {
         return 'method';
     }
@@ -275,21 +297,19 @@ method
     </screen>
    </example>
    <para>
-    That means that calling an <link linkend="functions.anonymous">anonymous
-    function</link> which has been assigned to a property is not directly
-    possible. Instead the property has to be assigned to a variable first, for
-    instance. As of PHP 7.0.0 it is possible to call such a property directly
-    by enclosing it in parentheses.
+    这意味着,如果你的类属性被分配给一个
+    <link linkend="functions.anonymous">匿名函数</link>
+    你将无法直接调用它。因为访问类属性的优先级要更高,在此场景下需要用括号包裹起来调用。
    </para>
    <example>
-    <title>Calling an anonymous function stored in a property</title>
+    <title>类属性被赋值为匿名函数时的调用示例</title>
     <programlisting role="php">
 <![CDATA[
 <?php
 class Foo
 {
     public $bar;
-    
+
     public function __construct() {
         $this->bar = function() {
             return 42;
@@ -299,11 +319,6 @@ class Foo
 
 $obj = new Foo();
 
-// as of PHP 5.3.0:
-$func = $obj->bar;
-echo $func(), PHP_EOL;
-
-// alternatively, as of PHP 7.0.0:
 echo ($obj->bar)(), PHP_EOL;
 ]]>
     </programlisting>
@@ -317,10 +332,12 @@ echo ($obj->bar)(), PHP_EOL;
   </sect2>
 
  <sect2 xml:id="language.oop5.basic.extends">
+  <!-- TODO Example about class constant redefinition -->
+  <!-- TODO Split into it's own page? -->
   <title>extends</title>
   <para>
    一个类可以在声明中用 <literal>extends</literal>
-   关键字继承另一个类的方法和属性。PHP不支持多重继承,一个类只能继承一个基类。
+   关键字继承另一个类的方法和属性。PHP 不支持多重继承,一个类只能继承一个基类。
   </para>
   <para>
    被继承的方法和属性可以通过用同样的名字重新声明被覆盖。但是如果父类定义方法时使用了
@@ -328,10 +345,6 @@ echo ($obj->bar)(), PHP_EOL;
    <link linkend="language.oop5.paamayim-nekudotayim">parent::</link>
    来访问被覆盖的方法或属性。
   </para>
-  <para>
-   当覆盖方法时,参数必须保持一致否则 PHP 将发出 <constant>E_STRICT</constant>
-   级别的错误信息。但构造函数例外,构造函数可在被覆盖时使用不同的参数。
-  </para>
   <example>
    <title>简单的类继承</title>
     <programlisting role="php">
@@ -339,7 +352,7 @@ echo ($obj->bar)(), PHP_EOL;
 <?php
 class ExtendClass extends SimpleClass
 {
-    // Redefine the parent method
+    // 同样名称的方法,将会覆盖父类的方法
     function displayVar()
     {
         echo "Extending class\n";
@@ -360,13 +373,176 @@ a default value
 ]]>
     </screen>
    </example>
- </sect2>
- 
+
+   <sect3 xml:id="language.oop.lsp">
+    <title>Signature compatibility rules</title>
+    <para>
+     When overriding a method, its signature must be compatible with the parent
+     method. Otherwise, a fatal error is emitted, or, prior to PHP 8.0.0, an
+     <constant>E_WARNING</constant> level error is generated.
+     A signature is compatible if it respects the
+     <link linkend="language.oop5.variance">variance</link> rules, makes a
+     mandatory parameter optional, and if any new parameters are optional.
+     This is known as the Liskov Substitution Principle, or LSP for short.
+     The <link linkend="language.oop5.decon.constructor">constructor</link>,
+     and <literal>private</literal> methods are exempt from these signature
+     compatibility rules, and thus won't emit a fatal error in case of a
+     signature mismatch.
+    </para>
+    <example>
+     <title>Compatible child methods</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+
+class Base
+{
+    public function foo(int $a) {
+        echo "Valid\n";
+    }
+}
+
+class Extend1 extends Base
+{
+    function foo(int $a = 5)
+    {
+        parent::foo($a);
+    }
+}
+
+class Extend2 extends Base
+{
+    function foo(int $a, $b = 5)
+    {
+        parent::foo($a);
+    }
+}
+
+$extended1 = new Extend1();
+$extended1->foo();
+$extended2 = new Extend2();
+$extended2->foo(1);
+]]>
+     </programlisting>
+     &example.outputs;
+     <screen>
+<![CDATA[
+Valid
+Valid
+]]>
+     </screen>
+    </example>
+
+    <para>
+     The following examples demonstrate that a child method which removes a parameter, or makes an optional
+     parameter mandatory, is not compatible with the parent method.
+    </para>
+    <example>
+     <title>Fatal error when a child method removes a parameter</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+
+class Base
+{
+    public function foo(int $a = 5) {
+        echo "Valid\n";
+    }
+}
+
+class Extend extends Base
+{
+    function foo()
+    {
+        parent::foo(1);
+    }
+}
+]]>
+     </programlisting>
+     &example.outputs.8.similar;
+     <screen>
+<![CDATA[
+Fatal error: Declaration of Extend::foo() must be compatible with Base::foo(int $a = 5) in /in/evtlq on line 13
+]]>
+     </screen>
+    </example>
+    <example>
+     <title>Fatal error when a child method makes an optional parameter mandatory</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+
+class Base
+{
+    public function foo(int $a = 5) {
+        echo "Valid\n";
+    }
+}
+
+class Extend extends Base
+{
+    function foo(int $a)
+    {
+        parent::foo($a);
+    }
+}
+]]>
+     </programlisting>
+     &example.outputs.8.similar;
+     <screen>
+<![CDATA[
+Fatal error: Declaration of Extend::foo(int $a) must be compatible with Base::foo(int $a = 5) in /in/qJXVC on line 13
+]]>
+     </screen>
+    </example>
+
+    <warning>
+     <para>
+      Renaming a method's parameter in a child class is not a signature
+      incompatibility. However, this is discouraged as it will result in a
+      runtime <classname>Error</classname> if
+      <link linkend="functions.named-arguments">named arguments</link>
+      are used.
+     </para>
+     <example>
+      <title>Error when using named arguments and parameters were renamed in a child class</title>
+      <programlisting role="php">
+<![CDATA[
+<?php
+
+class A {
+    public function test($foo, $bar) {}
+}
+
+class B extends A {
+    public function test($a, $b) {}
+}
+
+$obj = new B;
+
+// Pass parameters according to A::test() contract
+$obj->test(foo: "foo", bar: "bar"); // ERROR!
+]]>
+      </programlisting>
+      &example.outputs.similar;
+      <screen>
+<![CDATA[
+Fatal error: Uncaught Error: Unknown named parameter $foo in /in/XaaeN:14
+Stack trace:
+#0 {main}
+  thrown in /in/XaaeN on line 14
+]]>
+      </screen>
+     </example>
+    </warning>
+   </sect3>
+  </sect2>
+
   <sect2 xml:id="language.oop5.basic.class.class">
    <title>::class</title>
-   
+
    <para>
-    自 PHP 5.5 起,关键词 <literal>class</literal> 也可用于类名的解析。使用 <literal>ClassName::class</literal> 你可以获取一个字符串,包含了类 <literal>ClassName</literal> 的完全限定名称。这对使用了
+    关键词 <literal>class</literal> 也可用于类名的解析。使用 <literal>ClassName::class</literal> 你可以获取一个字符串,包含了类 <literal>ClassName</literal> 的完全限定名称。这对使用了
     <link linkend="language.namespaces">命名空间</link> 的类尤其有用。
    </para>
    <para>
@@ -378,7 +554,7 @@ a default value
 namespace NS {
     class ClassName {
     }
-    
+
     echo ClassName::class;
 }
 ?>
@@ -393,14 +569,98 @@ NS\ClassName
     </example>
    </para>
    <note>
-    <para>The class name resolution using <literal>::class</literal> is a
-     compile time transformation. That means at the time the class name string
-     is created no autoloading has happened yet. As a consequence, class names
-     are expanded even if the class does not exist. No error is issued in
-     that case.
+    <para>使用 <literal>::class</literal>
+     解析类名操作会在底层编译时进行。这意味着在执行该操作时,类还没有被加载。因此,即使要调用的类不存在,类名也会被展示。在此种场景下,并不会发生错误。
     </para>
+    <example xml:id="language.oop5.basic.class.class.fail">
+     <title>解析不存在的类名</title>
+     <programlisting role="php">
+<![CDATA[
+<?php
+print Does\Not\Exist::class;
+?>
+]]>
+     </programlisting>
+     &example.outputs;
+     <screen>
+<![CDATA[
+Does\Not\Exist
+]]>
+     </screen>
+    </example>
    </note>
+   <para>
+    自 PHP 8.0.0 起,<literal>::class</literal> 关键字也可以对象上使用。与上述情况不同,此时解析将会在运行时进行。此操作的运行结果和
+    <function>get_class</function> 函数一致。
+   </para>
+   <example xml:id="language.oop5.basic.class.class.object">
+    <title>类名解析</title>
+    <programlisting role="php">
+<![CDATA[
+<?php
+namespace NS {
+    class ClassName {
+    }
+}
+$c = new ClassName();
+print $c::class;
+?>
+]]>
+    </programlisting>
+    &example.outputs;
+    <screen>
+<![CDATA[
+NS\ClassName
+]]>
+    </screen>
+   </example>
   </sect2>
+ <sect2 xml:id="language.oop5.basic.nullsafe">
+  <title>Nullsafe 方法和属性</title>
+  <para>
+   自 PHP 8.0.0 起,类属性和方法新增加了一个 "nullsafe" 操作符:
+   <literal>?-></literal>。The nullsafe operator
+   works the same as property or method access as above, except that if the
+   object being dereferenced is &null; then &null;
+   will be returned rather than an exception thrown. If the dereference is part of a
+   chain, the rest of the chain is skipped.
+  </para>
+  <para>
+   此操作的结果,类似于在每次访问前使用 <function>is_null</function> 函数判断方法和属性是否存在,但更加简洁。
+  </para>
+  <para>
+   <example>
+    <title>Nullsafe 操作符</title>
+    <programlisting role="php">
+<![CDATA[
+<?php
+
+// 自 PHP 8.0.0 起可用
+$result = $repository?->getUser(5)?->name;
+
+// 上边那行代码等价于以下代码
+if (is_null($repository)) {
+    $result = null;
+} else {
+    $user = $repository->getUser(5);
+    if (is_null($user)) {
+        $result = null;
+    } else {
+        $result = $user->name;
+    }
+}
+?>
+]]>
+    </programlisting>
+   </example>
+  </para>
+  <note>
+   <para>
+    仅当 null 被认为是属性或方法返回的有效和预期的可能值时,才推荐使用 nullsafe
+    操作符。如果业务中需要明确指示错误,抛出异常会是更好的处理方式。
+   </para>
+  </note>
+ </sect2>
 </sect1>
 
 <!-- Keep this comment at the end of the file