svn: /phpdoc/ru/trunk/language/ control-structures/match.xml exceptions.xml types/declarations.xml
[email protected] (Andrey Gromov) Thu, 26 Nov 2020 11:53:26 +0000
| Newsgroups | php.doc.ru |
|---|---|
| Message-ID | <[email protected]> |
rjhdby Thu, 26 Nov 2020 11:53:26 +0000
Revision: http://svn.php.net/viewvc?view=revision&revision=351668
Log:
new
Changed paths:
A phpdoc/ru/trunk/language/control-structures/match.xml
U phpdoc/ru/trunk/language/exceptions.xml
A phpdoc/ru/trunk/language/types/declarations.xml
svn-diffs-351668.txt
(text/x-diff, 47.2 KB)
Added: phpdoc/ru/trunk/language/control-structures/match.xml
===================================================================
--- phpdoc/ru/trunk/language/control-structures/match.xml (rev 0)
+++ phpdoc/ru/trunk/language/control-structures/match.xml 2020-11-26 11:53:26 UTC (rev 351668)
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- $Revision$ -->
+<!-- EN-Revision: 351515 Maintainer: rjhdby Status: ready -->
+<!-- Reviewed: no -->
+
+<sect1 xml:id="control-structures.match" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
+ <title><literal>match</literal></title>
+ <?phpdoc print-version-for="match"?>
+ <para>
+ Выражение <literal>match</literal> предназначено для ветвления потока исполнения на
+ основании проверки совпадения значения с заданным условием.
+ Аналогично оператору <literal>switch</literal>, выражение
+ <literal>match</literal> принимает на вход выражение, которое сравнивается
+ с множеством альтернатив. Но, в отличии от <literal>switch</literal>,
+ оно обрабатывает значение в стиле, больше похожем на тернарный оператор.
+ Также, в отличии от <literal>switch</literal>, используется строгое сравнение
+ (<code>===</code>), а не слабое (<code>==</code>).
+ Выражение match доступно начиная с PHP 8.0.0.
+ </para>
+
+ <example>
+ <title>Структура выражения <literal>match</literal></title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+$return_value = match (subject_expression) {
+ single_conditional_expression => return_expression,
+ conditional_expression1, conditional_expression2 => return_expression,
+};
+?>
+]]>
+ </programlisting>
+
+ <note>
+ <simpara>
+ Результат <literal>match</literal> использовать не обязательно.
+ </simpara>
+ </note>
+ <note>
+ <simpara>
+ Выражение <literal>match</literal> <emphasis>должно</emphasis> завершаться
+ точкой с запятой <literal>;</literal>.
+ </simpara>
+ </note>
+ </example>
+
+ <para>
+ Выражение <literal>match</literal> похоже на оператор
+ <literal>switch</literal> за исключением некоторых ключевых отличий:
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ В отличии от switch, в <literal>match</literal> используется строгое сравнение (<code>===</code>).
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Выражение <literal>match</literal> возвращает результат.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ В <literal>Match</literal> исполняется только одна, первая подошедшая, ветвь кода, тогда как
+ в <literal>switch</literal> происходит сквозное исполнение начиная с подошедшего условия и
+ до первого встретившегося оператора <literal>brake</literal>.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Выражение <literal>match</literal> должно быть исчерпывающим.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ Также как и оператор <literal>switch</literal>, <literal>match</literal>
+ последовательно проводит проверки на совпадение с заданными условиями.
+ Выполнения кода условий происходит лениво, т.е. код следующего условия выполняется только
+ если все предыдущие проверки провалились. И выполнено будет только одна ветвь кода,
+ соответствующая подошедшему условию.
+ пример:
+ <informalexample>
+ <programlisting role="php">
+<![CDATA[
+<?php
+$result = match ($x) {
+ foo() => ...,
+ $this->bar() => ..., // bar() не будет выполнен, если foo() === $x
+ $this->baz => beep(), // beep() будет выполнен только если $x === $this->baz
+ // etc.
+};
+?>
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+
+ <para>
+ Условия в <literal>match</literal> могут быть множественными. В этом случае их следует разделять запятыми.
+ Множественные условия работают по принципу логического ИЛИ и, по сути, являются
+ сокращённой формой для случаев, когда несколько условий должны обрабатываться идентично.
+ </para>
+ <para>
+ <informalexample>
+ <programlisting role="php">
+<![CDATA[
+<?php
+$result = match ($x) {
+ // Множественное условие:
+ $a, $b, $c => 5,
+ // Аналогично трём одиночным:
+ $a => 5,
+ $b => 5,
+ $c => 5,
+};
+?>
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+ <para>
+ Также можно использовать шаблон <literal>default</literal>.
+ Этот шаблон совпадает с чем угодно, для чего не нашлось совпадений раньше.
+ К примеру:
+ <informalexample>
+ <programlisting role="php">
+<![CDATA[
+<?php
+$expressionResult = match ($condition) {
+ 1, 2 => foo(),
+ 3, 4 => bar(),
+ default => baz(),
+};
+?>
+]]>
+ </programlisting>
+ </informalexample>
+ <note>
+ <simpara>
+ Использование нескольких шаблонов default приведет к фатальной ошибке
+ <constant>E_FATAL_ERROR</constant>.
+ </simpara>
+ </note>
+ </para>
+
+ <para>
+ Выражение <literal>match</literal> должно быть исчерпывающим. Если
+ проверяемое выражение не совпало ни с одним из условий, то будет
+ выброшено исключение <classname>UnhandledMatchError</classname>.
+ </para>
+
+ <example>
+ <title>Пример не обрабтанного выраженияо</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+$condition = 5;
+
+try {
+ match ($condition) {
+ 1, 2 => foo(),
+ 3, 4 => bar(),
+ };
+} catch (\UnhandledMatchError $e) {
+ var_dump($e);
+}
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+object(UnhandledMatchError)#1 (7) {
+ ["message":protected]=>
+ string(33) "Unhandled match value of type int"
+ ["string":"Error":private]=>
+ string(0) ""
+ ["code":protected]=>
+ int(0)
+ ["file":protected]=>
+ string(9) "/in/ICgGK"
+ ["line":protected]=>
+ int(6)
+ ["trace":"Error":private]=>
+ array(0) {
+ }
+ ["previous":"Error":private]=>
+ NULL
+}
+]]>
+ </screen>
+ </example>
+
+ <sect2>
+ <title>Использование match для проверки сложных условий</title>
+ <para>
+ Выражение <literal>match</literal> можно использовать не только для проверки идентичности,
+ но и для любых выражений возвращающих логическое значение. В этом случае в качестве входного
+ параметра передаётся выражение <code>true</code>.
+ </para>
+
+ <example>
+ <title>Использование match для ветвления в зависимости от вхождения в диапазоны целых чисел</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+
+$age = 23;
+
+$result = match (true) {
+ $age >= 65 => 'пожилой',
+ $age >= 25 => 'взрослый',
+ $age >= 18 => 'совершеннолетний',
+ default => 'ребёнок',
+}
+
+var_dump($result);
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+string(11) "совершеннолетний"
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Использование match для ветвления в зависимости от содержимого строки</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+
+$text = 'Bienvenue chez nous';
+
+$result = match (true) {
+ str_contains($text, 'Welcome') || str_contains($text, 'Hello') => 'en',
+ str_contains($text, 'Bienvenue') || str_contains($text, 'Bonjour') => 'fr',
+ // ...
+};
+
+var_dump($result);
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+string(2) "fr"
+]]>
+ </screen>
+ </example>
+ </sect2>
+</sect1>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
Property changes on: phpdoc/ru/trunk/language/control-structures/match.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
\ No newline at end of property
Modified: phpdoc/ru/trunk/language/exceptions.xml
===================================================================
--- phpdoc/ru/trunk/language/exceptions.xml 2020-11-26 10:55:52 UTC (rev 351667)
+++ phpdoc/ru/trunk/language/exceptions.xml 2020-11-26 11:53:26 UTC (rev 351668)
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- EN-Revision: 351112 Maintainer: irker Status: ready -->
+<!-- EN-Revision: 351652 Maintainer: irker Status: ready -->
<!-- Reviewed: yes -->
<!-- $Revision$ -->
<chapter xml:id="language.exceptions" xmlns="http://docbook.org/ns/docbook">
@@ -192,21 +192,41 @@
перехватить исключение. Каждый блок &try;
должен иметь как минимум один соответствующий ему блок &catch; или &finally;.
</para>
-
<para>
+ В случае, если выброшено исключение, для которого нет блока &catch; в текущей функции,
+ это исключение будет "всплывать" по стеку вызова, пока не будет найден
+ подходящий блок &catch;. При этом, все встреченные блоки &finally; бдут исполнены.
+ Если стек вызовов раскрутится до глобальной области видимости, не встретив подходящего
+ блока &catch;, программа завершит работу с фатальной ошибкой, если только у вас
+ не настроен глобальный обработчик исключений.
+ </para>
+ <para>
Генерируемый объект должен принадлежать классу <classname>Exception</classname>
или наследоваться от <classname>Exception</classname>. Попытка сгенерировать
исключение другого класса приведет к фатальной ошибке PHP.
</para>
+ <para>
+ Начиная с PHP 8.0.0, ключевое слово &throw; является выражением и может использоваться
+ в контексте других выражений. В более ранних версиях оно являлось оператором и требовало
+ размещения в отдельной строке.
+ </para>
</simplesect>
<simplesect xml:id="language.exceptions.catch">
<title><literal>catch</literal></title>
<para>
+ Блок &catch; определяет то, как следует реагировать на выброшенное исключение.
+ В блоке &catch; указывается один или более типов исключений или ошибок(Error), которые он
+ будет обрабатывать. Также указывается и переменная, которой будет присвоено
+ пойманное исключение (начиная с PHP 8.0.0 задавать эту переменную не обязательно).
+ Выброшенное исключение или ошибка будут обработаны первым подходящим блоком &catch;.
+ </para>
+ <para>
Можно использовать несколько блоков &catch;, перехватывающих различные классы
исключений. Нормальное выполнение (когда не генерируются исключения в блоках
&try;) будет продолжено за последним блоком &catch;. Исключения могут быть
сгенерированы (или вызваны еще раз) оператором &throw; внутри блока &catch;.
+ Если нет, то исполнение будет продолжено после отработки блока &catch;.
</para>
<para>
При генерации исключения код, следующий после описываемого выражения,
@@ -218,10 +238,15 @@
функции <function>set_exception_handler</function>.
</para>
<para>
- В PHP 7.1 и выше, блок &catch; может принимать несколько типов исключений с помощью
- символа (<literal>|</literal>). Это полезно, когда разные исключения из разных иерархий классов
- обрабатываются одинаково.
+ Начиная с PHP 7.1.0, блок &catch; может принимать несколько типов исключений с помощью
+ символа (<literal>|</literal>). Это полезно, когда разные исключения из разных
+ иерархий классов обрабатываются одинаково.
</para>
+ <para>
+ Начиная с PHP 8.0.0, задание переменной для пойманного исключения опционально.
+ Если она не задана, блок &catch; будет исполняться, но не будет иметь доступа
+ к объекту исключения.
+ </para>
</simplesect>
<simplesect xml:id="language.exceptions.finally">
@@ -240,6 +265,18 @@
</para>
</simplesect>
+ <simplesect xml:id="language.exceptions.exception-handler">
+ <title><literal>Глобальный обработчик исключений</literal></title>
+ <para>
+ Если исключение дошло по стеку вызовов до глобальной области видимости, оно может быть
+ обработано глобальным обработчиком исключений, если он задан.
+ С помощью функции <function>set_exception_handler</function> можно задать функцию,
+ которая будет выполнена вместо блока &catch;, если не нашлось подходящего. Эффект
+ аналогичен тому, как будто мы всю нашу программу обернули в блок &try;-&catch;, где
+ за реализацию блока &catch; отвечает установленная функция.
+ </para>
+ </simplesect>
+
<simplesect xml:id="language.exceptions.notes">
&reftitle.notes;
@@ -250,7 +287,22 @@
новые <link linkend="language.oop5">объектно-ориентированные</link>
расширения используют исключения. Однако, ошибки можно легко преобразовать
в исключения с помощью класса <link linkend="class.errorexception">ErrorException</link>.
+ Однако это не сработает для фатальных ошибок.
</para>
+ <example>
+ <title>Преобразование сообщения об ошибках в исключение</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function exceptions_error_handler($severity, $message, $filename, $lineno) {
+ throw new ErrorException($message, 0, $severity, $filename, $lineno);
+}
+
+set_error_handler('exceptions_error_handler');
+?>
+]]>
+ </programlisting>
+ </example>
</note>
<tip>
<para>
@@ -328,9 +380,9 @@
echo "Привет, мир\n";
?>
]]>
- </programlisting>
- &example.outputs;
- <screen>
+ </programlisting>
+ &example.outputs;
+ <screen>
<![CDATA[
0.2
Первый блок finally.
@@ -338,11 +390,11 @@
Второй блок finally.
Привет, мир
]]>
- </screen>
+ </screen>
</example>
<example>
- <title>Взаимодействие между блоками &finally; и &return;</title>
- <programlisting role="php">
+ <title>Взаимодействие между блоками &finally; и &return;</title>
+ <programlisting role="php">
<![CDATA[
<?php
@@ -359,14 +411,14 @@
echo test();
?>
]]>
- </programlisting>
- &example.outputs;
- <screen>
+ </programlisting>
+ &example.outputs;
+ <screen>
<![CDATA[
finally
]]>
- </screen>
- </example>
+ </screen>
+ </example>
<example>
<title>Вложенные исключения</title>
<programlisting role="php">
@@ -395,13 +447,13 @@
?>
]]>
- </programlisting>
- &example.outputs;
- <screen>
+ </programlisting>
+ &example.outputs;
+ <screen>
<![CDATA[
string(4) "foo!"
]]>
- </screen>
+ </screen>
</example>
<example>
<title>Обработка нескольких исключений в одном блоке catch</title>
@@ -428,14 +480,58 @@
?>
]]>
- </programlisting>
- &example.outputs;
- <screen>
+ </programlisting>
+ &example.outputs;
+ <screen>
<![CDATA[
string(11) "MyException"
]]>
- </screen>
+ </screen>
</example>
+ <example>
+ <title>Пример блока &catch; без указания переменной</title>
+ <para>Допустимо начиная с PHP 8.0.0</para>
+ <programlisting role="php">
+<![CDATA[
+<?php
+
+class SpecificException extends Exception {}
+
+function test() {
+ throw new SpecificException('Ой!');
+}
+
+try {
+ test();
+} catch (SpecificException) {
+ print "Было поймано исключение SpecificException, но нам безразлично, что у него внутри.";
+}
+?>
+]]>
+ </programlisting>
+ </example>
+ <example>
+ <title>Throw как выражение</title>
+ <para>Only permitted in PHP 8.0.0 and later.</para>
+ <programlisting role="php">
+<![CDATA[
+<?php
+
+class SpecificException extends Exception {}
+
+function test() {
+ do_something_risky() or throw new Exception('Всё сломалось');
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ print $e->getMessage();
+}
+?>
+]]>
+ </programlisting>
+ </example>
</simplesect>
</chapter>
Added: phpdoc/ru/trunk/language/types/declarations.xml
===================================================================
--- phpdoc/ru/trunk/language/types/declarations.xml (rev 0)
+++ phpdoc/ru/trunk/language/types/declarations.xml 2020-11-26 11:53:26 UTC (rev 351668)
@@ -0,0 +1,803 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- $Revision$ -->
+<!-- EN-Revision: 351382 Maintainer: rjhdby Status: ready -->
+<!-- Reviewed: no -->
+
+<sect1 xml:id="language.types.declarations">
+ <title>Объявление типов</title>
+
+ <para>
+ Объявления типов могут использоваться для аргументов функций, возвращаемых значений и,
+ начиная с PHP 7.4.0, для свойств класса. Они используются во время исполнения для проверки,
+ что значение имеет точно тот тип, который для них указан. В противном случае будет выброшено
+ исключение <classname>TypeError</classname>.
+ </para>
+
+ <!-- Find better place where to put this note -->
+ <note>
+ <!-- TODO Link to covariance section -->
+ <para>
+ При переопределении родительского метода, тип возвращаемого значения дочернего метода должен
+ соответствовать любому объявлению возвращаемого типа родительского. Если в родительском
+ методе тип возвращаемого значения не объявлен, то это можно сделать в дочернем.
+ </para>
+ </note>
+
+ <sect2 xml:id="language.types.declarations.base">
+ <title>Одиночные типы</title>
+ <informaltable>
+ <tgroup cols="3">
+ <thead>
+ <row>
+ <entry>&Type;</entry>
+ <entry>&Description;</entry>
+ <entry>&Version;</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>Имя класса/интерфейса</entry>
+ <entry>
+ Значение должно представлять собой &instanceof; заданного класса или интерфейса.
+ </entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><type>self</type></entry>
+ <entry>
+ Значение должно представлять собой &instanceof; того же класса, в котором определён метод.
+ Может использоваться только в классах.
+ </entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><type>array</type></entry>
+ <entry>
+ Значение должно быть типа <type>array</type>.
+ </entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><type>callable</type></entry>
+ <entry>
+ Значение должно быть корректным <type>callable</type>.
+ Нельзя использовать в качестве объявления для свойств класса.
+ </entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><type>bool</type></entry>
+ <entry>
+ Значение должно быть логического типа.
+ </entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><type>float</type></entry>
+ <entry>
+ Значение должно быть числом с плавающей запятой.
+ </entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><type>int</type></entry>
+ <entry>
+ Значение должно быть целым числом.
+ </entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><type>string</type></entry>
+ <entry>
+ Значение должно быть строкой (тип <type>string</type>).
+ </entry>
+ <entry></entry>
+ </row>
+ <row>
+ <entry><type>iterable</type></entry>
+ <entry>
+ Значение может быть либо массивом (тип <type>array</type>) или представлять собой
+ &instanceof; <classname>Traversable</classname>.
+ </entry>
+ <entry>PHP 7.1.0</entry>
+ </row>
+ <row>
+ <entry><type>object</type></entry>
+ <entry>
+ Значение должно быть объектом (тип <type>object</type>).
+ </entry>
+ <entry>PHP 7.2.0</entry>
+ </row>
+ <row>
+ <entry><type>mixed</type></entry>
+ <entry>
+ Значение может иметь любой тип.
+ </entry>
+ <entry>PHP 8.0.0</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+
+ <warning>
+ <para>
+ Псевдонимы для указанных выше скалярных типов не поддерживаются.
+ В случае использования они будут считаться за имя класса или интерфейса.
+ К примеру, при использовании в качестве типа <literal>boolean</literal>, он будет
+ ожидать, что значение представляет собой &instanceof; класса или интерфейса
+ <literal>boolean</literal>, а не значение типа <type>bool</type>:
+ </para>
+ <para>
+ <example>
+ <programlisting role="php">
+<![CDATA[
+<?php
+ function test(boolean $param) {}
+ test(true);
+?>
+]]>
+ </programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2
+
+Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type boolean, bool given, called in - on line 3 and defined in -:2
+Stack trace:
+#0 -(3): test(true)
+#1 {main}
+ thrown in - on line 2
+]]>
+ </screen>
+ </example>
+ </para>
+ </warning>
+
+ <sect3 xml:id="language.types.declarations.examples">
+ &reftitle.examples;
+ <example>
+ <title>Объявление типа для класса</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+class C {}
+class D extends C {}
+
+// Не является наследником C.
+class E {}
+
+function f(C $c) {
+ echo get_class($c)."\n";
+}
+
+f(new C);
+f(new D);
+f(new E);
+?>
+]]>
+ </programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+C
+D
+
+Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
+Stack trace:
+#0 -(14): f(Object(E))
+#1 {main}
+ thrown in - on line 8
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Объявление типа для интерфейса</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+interface I { public function f(); }
+class C implements I { public function f() {} }
+
+// Не реализует интерфейс I.
+class E {}
+
+function f(I $i) {
+ echo get_class($i)."\n";
+}
+
+f(new C);
+f(new E);
+?>
+]]>
+ </programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+C
+
+Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
+Stack trace:
+#0 -(13): f(Object(E))
+#1 {main}
+ thrown in - on line 8
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Объявление типа возвращаемого значения</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function sum($a, $b): float {
+ return $a + $b;
+}
+
+// Обратите внимание, что будет возвращено число с плавающей запятой.
+var_dump(sum(1, 2));
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+float(3)
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Возвращение объекта</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+class C {}
+
+function getC(): C {
+ return new C;
+}
+
+var_dump(getC());
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+object(C)#1 (0) {
+}
+]]>
+ </screen>
+ </example>
+ </sect3>
+ </sect2>
+
+ <sect2 xml:id="language.types.declarations.nullable">
+ <title>Обнуляемые типы</title>
+
+ <para>
+ Начиная с PHP 7.1.0, объявления типов могут быть помечены как обнуляемые, путём
+ добавления префикса в виде знака вопроса(<literal>?</literal>).
+ Это означает, что значение может быть как объявленного типа, так и быть равным &null;.
+ </para>
+
+ <para>
+ <example>
+ <title>Объявление обнуляемых типов</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+class C {}
+
+function f(?C $c) {
+ var_dump($c);
+}
+
+f(new C);
+f(null);
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+object(C)#1 (0) {
+}
+NULL
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Обнуляемые типы для возвращаемого значения</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function get_item(): ?string {
+ if (isset($_GET['item'])) {
+ return $_GET['item'];
+ } else {
+ return null;
+ }
+}
+?>
+]]>
+ </programlisting>
+ </example>
+ </para>
+
+ <note>
+ <para>
+ До PHP 7.1.0, было возможно задавать обнуляемые типы аргументов функций путём
+ задания значения по умолчанию равного <literal>null</literal>.
+ Так делать не рекомендуется, поскольку это может поломать наследование.
+ </para>
+ <example>
+ <title>Старый способ задавать обнуляемые типы для аргументов</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+class C {}
+
+function f(C $c = null) {
+ var_dump($c);
+}
+
+f(new C);
+f(null);
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+object(C)#1 (0) {
+}
+NULL
+]]>
+ </screen>
+ </example>
+ </note>
+ </sect2>
+
+ <sect2 xml:id="language.types.declarations.union">
+ <title>Объединённые типы</title>
+ <para>
+ Объединённые типы позволяют использовать несколько типов, а не исключительно один.
+ Для их объявления используется следующий синтаксис <literal>T1|T2|...</literal>.
+ Объединённые типы доступны начиная с PHP 8.0.0.
+ </para>
+
+ <sect3 xml:id="language.types.declarations.union.nullable">
+ <title>Обнуляемые объединённые типы</title>
+ <para>
+ Тип <literal>null</literal> можно использовать как часть объединений следующим образов:
+ <literal>T1|T2|null</literal>.
+ Существующая нотация <literal>?T</literal> рассматривается как сокращение для <literal>T|null</literal>.
+ </para>
+
+ <caution>
+ <simpara>
+ <literal>null</literal> не может использоваться как отдельный тип.
+ </simpara>
+ </caution>
+ </sect3>
+
+ <sect3 xml:id="language.types.declarations.union.false">
+ <title>Псевдо-тип false</title>
+ <para>
+ Псевдо-тип <literal>false</literal> поддерживается как часть объединённых типов.
+ Он добавлен по историческим причинам, так как многие встроеные функции возвращают
+ <literal>false</literal> вместо <literal>null</literal> в случае ошибок.
+ Классический пример - функция <function>strpos</function>.
+ </para>
+
+ <caution>
+ <simpara>
+ <literal>false</literal> нельзя использовать как самостоятельный тип (включая
+ обнуляемый вариант).
+ Таким образом, все объявления такого типа недопустимы: <literal>false</literal>, <literal>false|null</literal>
+ и <literal>?false</literal>.
+ </simpara>
+ </caution>
+ <caution>
+ <simpara>
+ Обратите внимание, что псевдо-тип <literal>true</literal> <emphasis>не</emphasis> существует.
+ </simpara>
+ </caution>
+ </sect3>
+
+ <sect3 xml:id="language.types.declarations.union.redundant">
+ <title>Дублирующиеся и повторяющиеся типы</title>
+ <para>
+ Для отлова простых ошибок в объединённых объявлениях, повторяющиеся типы, которые
+ можно отследить без загрузки класса, приведут к ошибке компиляции.
+ В том числе:
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ Каждый тип распознаваемый по имени должен встречаться только один раз.
+ Типы вида <literal>int|string|INT</literal> приведут к ошибке.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Если используется <type>bool</type>, то использовать дополнительно <type>false</type> нельзя.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Если используется тип <type>object</type>, то дополнительное использование имён классов недопустимо.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Если используется <type>iterable</type>, то к нему нельзя добавить <type>array</type>
+ или <classname>Traversable</classname>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <note>
+ <simpara>
+ Это не гарантирует, что все объединённые типы объявлены корректно, поскольку
+ такая проверка потребует загрузки всех используемых классов.
+ </simpara>
+ </note>
+
+ <para>
+ К примеру, если <literal>A</literal> и <literal>B</literal> являются псевдонимами одного и того же класса,
+ то <literal>A|B</literal> выглядит как корректный объединённый тип, даже если фактически объявление
+ может быть сокращено до <literal>A</literal> или <literal>B</literal>.
+ Аналогично, если <code>B extends A {}</code>, то <literal>A|B</literal> тоже
+ выглядит корректным типом, не смотря на то, что он может быть сокращён до
+ <literal>A</literal>.
+
+ <informalexample>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function foo(): int|INT {} // Запрещено
+function foo(): bool|false {} // Запрещено
+
+use A as B;
+function foo(): A|B {} // Запрещено ("use" является частью разрешения имён)
+
+class_alias('X', 'Y');
+function foo(): X|Y {} // Допустимо (повторение будет определено только во время выполнения)
+?>
+]]>
+ </programlisting>
+ </informalexample>
+ </para>
+ </sect3>
+
+ </sect2>
+
+ <sect2 xml:id="language.types.declarations.return-only">
+ <title>Типы, подходящие только для возвращаемого значения</title>
+
+ <sect3 xml:id="language.types.declarations.void">
+ <title>void</title>
+ <para>
+ Тип <literal>void</literal> означает, что функция ничего не возвращает.
+ Соответственно он не может быть частью объединения.
+ Доступно с PHP 7.1.0.
+ </para>
+ </sect3>
+
+ <sect3 xml:id="language.types.declarations.static">
+ <title>static</title>
+ <para>
+ Значение должно представлять собой &instanceof; того же класса, в котором был вызван метод.
+ Доступно с PHP 8.0.0.
+ </para>
+ </sect3>
+ </sect2>
+
+ <sect2 xml:id="language.types.declarations.strict">
+ <title>Строгое типизирование</title>
+
+ <para>
+ По умолчанию, PHP будет преобразовывать значения неправильного типа в ожидаемые.
+ К примеру, если в функцию передать параметр типа <type>int</type> в аргумент,
+ объявленный как <type>string</type>, то он преобразуется в <type>string</type>.
+ </para>
+
+ <para>
+ Можно включить режим строгого типизирования на уровне файла. В этом
+ режиме, тип значения должен строго соответствовать объявленому, иначе будет выброшено
+ исключение <classname>TypeError</classname>.
+ Единственным исключением из этого правила является передача значения типа <type>int</type>
+ туда, где ожидается <type>float</type>.
+ </para>
+
+ <warning>
+ <simpara>
+ На вызовы из внутренних функций, действие <literal>strict_types</literal> не распространяется.
+ </simpara>
+ </warning>
+
+ <para>
+ Для включения строгой типизации используется оператор &declare; с объявлением
+ <literal>strict_types</literal>:
+ </para>
+
+ <note>
+ <para>
+ Строгая типизация применяется к вызовам функций, сделанным
+ <emphasis>изнутри</emphasis> файла с включенной строгой типизацией,
+ а не к функциям, объявленным в этом файле. Если из файла без включенной строгой
+ типизации вызывается функция, которая была определена в файле со строгой типизацией,
+ то будет использованы его предпочтения по типизации - т.е. правила строгой типизации
+ будут проигнорированы и для значений будет применяться приведение типов.
+ </para>
+ </note>
+
+ <note>
+ <para>
+ Строгая типизация определяется только для объявлений скалярных типов.
+ </para>
+ </note>
+
+ <example>
+ <title>Строгая типизация для значений аргументов</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+declare(strict_types=1);
+
+function sum(int $a, int $b) {
+ return $a + $b;
+}
+
+var_dump(sum(1, 2));
+var_dump(sum(1.5, 2.5));
+?>
+]]>
+ </programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+int(3)
+
+Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 9 and defined in -:4
+Stack trace:
+#0 -(9): sum(1.5, 2.5)
+#1 {main}
+ thrown in - on line 4
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Приведение типов для значений аргументов</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function sum(int $a, int $b) {
+ return $a + $b;
+}
+
+var_dump(sum(1, 2));
+
+// Переданные значения будут приведены к целым числам: обратите внимание на вывод ниже!
+var_dump(sum(1.5, 2.5));
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+int(3)
+int(3)
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Строгая типизация для возвращаемых значений</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+declare(strict_types=1);
+
+function sum($a, $b): int {
+ return $a + $b;
+}
+
+var_dump(sum(1, 2));
+var_dump(sum(1, 2.5));
+?>
+]]>
+ </programlisting>
+ &example.outputs;
+ <screen>
+<![CDATA[
+int(3)
+
+Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5
+Stack trace:
+#0 -(9): sum(1, 2.5)
+#1 {main}
+ thrown in - on line 5
+]]>
+ </screen>
+ </example>
+ </sect2>
+
+ <sect2 xml:id="language.types.declarations.union.coercive">
+ <title>Приведение для объеденённых типов</title>
+ <para>
+ Если <literal>strict_types</literal> не разрешено, то объявления скалярных типов
+ подлежат ограниченному неявному приведению. Если фактический тип не является частью объединения,
+ то используется следующий порядок приведения типов:
+
+ <orderedlist>
+ <listitem>
+ <simpara>
+ <type>int</type>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <type>float</type>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <type>string</type>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <type>bool</type>
+ </simpara>
+ </listitem>
+ </orderedlist>
+
+ Если тип присутствует в объединении и значение может быть приведено к нему основываясь на
+ существующей семантике приведения типов PHP, то поизойдёт приведение к нему. Если нет, то
+ проверится следующий тип в списке.
+ </para>
+
+ <caution>
+ <para>
+ Единственным исключением является приведение строки в случае, если в объединении
+ одновременно присутствуют и <type>int</type> и <type>float</type>. В таком случае будет
+ выбрано наиболее подходящий тип по правилу приведения "числовых строк".
+ К примеру, для <literal>"42"</literal> бдет выбран тип <type>int</type>,
+ а для <literal>"42.0"</literal> тип <type>float</type>.
+ </para>
+ </caution>
+
+ <note>
+ <para>
+ Типы, не входящие в данный список не подходят для целей неявного приведения.
+ targets for implicit coercion. В часности, для <literal>null</literal>
+ и <literal>false</literal> неявного приведения не случится.
+ </para>
+ </note>
+
+ <example>
+ <title>Пример приведения для объединённых типов</title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+// int|string
+42 --> 42 // явный тип
+"42" --> "42" // явный тип
+new ObjectWithToString --> строка с результатом выполнения __toString()
+ // Объекты никогда не будут приведены к целому числу, даже если вернут "числовую строку"
+42.0 --> 42 // float совместим с int
+42.1 --> 42 // float совместим с int
+1e100 --> "1.0E+100" // float слишком большой для типа int, преобразуется в строку
+INF --> "INF" // float слишком большой для типа int, преобразуется в строку
+true --> 1 // bool совместим с int
+[] --> TypeError // array не совместим ни с int ни со string
+
+// int|float|bool
+"45" --> 45 // целочисленная "чистовая строка"
+"45.0" --> 45.0 // "чистовая строка" с плавающей запятой
+
+"45X" --> true // не "чистовая строка", приведётся к bool
+"" --> false // не "чистовая строка", приведётся к bool
+"X" --> true // не "чистовая строка", приведётся к bool
+[] --> TypeError // array не совместим ни с int ни с float ни с bool
+?>
+]]>
+ </programlisting>
+ </example>
+ </sect2>
+
+ <!-- TODO figure out what do to with these things -->
+ <sect2 xml:id="language.types.declarations.misc">
+ <title>Дополнительно</title>
+ <example>
+ <title>Типизированые параметры передаваемые по ссылке</title>
+ <simpara>
+ Объявление типов для параметров передаваемых по ссылке проверяется только на этапе вызова функции.
+ Не никакой гарантии, что после выхода из функции тип переменной останется неизменным.
+ </simpara>
+ <programlisting role="php">
+<![CDATA[
+<?php
+function array_baz(array &$param)
+{
+ $param = 1;
+}
+$var = [];
+array_baz($var);
+var_dump($var);
+array_baz($var);
+?>
+]]>
+ </programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+int(1)
+
+Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
+Stack trace:
+#0 -(9): array_baz(1)
+#1 {main}
+ thrown in - on line 2
+]]>
+ </screen>
+ </example>
+
+ <example>
+ <title>Обработка <classname>TypeError</classname></title>
+ <programlisting role="php">
+<![CDATA[
+<?php
+declare(strict_types=1);
+
+function sum(int $a, int $b) {
+ return $a + $b;
+}
+
+try {
+ var_dump(sum(1, 2));
+ var_dump(sum(1.5, 2.5));
+} catch (TypeError $e) {
+ echo 'Ошибка: ', $e->getMessage();
+}
+?>
+]]>
+ </programlisting>
+ &example.outputs.8;
+ <screen>
+<![CDATA[
+int(3)
+Ошибка: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 10
+]]>
+ </screen>
+ </example>
+ </sect2>
+
+</sect1>
+
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omittag:t
+sgml-shorttag:t
+sgml-minimize-attributes:nil
+sgml-always-quote-attributes:t
+sgml-indent-step:1
+sgml-indent-data:t
+indent-tabs-mode:nil
+sgml-parent-document:nil
+sgml-default-dtd-file:"~/.phpdoc/manual.ced"
+sgml-exposed-tags:nil
+sgml-local-catalogs:nil
+sgml-local-ecat-files:nil
+End:
+vim600: syn=xml fen fdm=syntax fdl=2 si
+vim: et tw=78 syn=sgml
+vi: ts=1 sw=1
+-->
Property changes on: phpdoc/ru/trunk/language/types/declarations.xml
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Id Rev Revision Date LastChangedDate LastChangedRevision Author LastChangedBy HeadURL URL
\ No newline at end of property