mirror of
https://github.com/php/doc-ru.git
synced 2026-04-25 08:18:16 +02:00
210 lines
9.3 KiB
XML
210 lines
9.3 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
||
<!-- EN-Revision: f94d903985119d3ac00f4528551df947f57b667f Maintainer: mch Status: ready -->
|
||
<!-- Reviewed: no -->
|
||
<sect1 xml:id="language.oop5.inheritance" xmlns="http://docbook.org/ns/docbook">
|
||
<title>Наследование</title>
|
||
<para>
|
||
Наследование — это хорошо зарекомендовавший себя принцип программирования, и PHP
|
||
использует этот принцип в своей объектной модели. Этот принцип повлияет на то,
|
||
как многие классы и объекты связаны друг с другом.
|
||
</para>
|
||
<para>
|
||
Например, при расширении класса дочерний класс наследует все
|
||
общедоступные и защищённые методы, свойства и константы родительского класса.
|
||
До тех пор пока
|
||
эти методы не будут переопределены, они будут сохранять свою
|
||
исходную функциональность.
|
||
</para>
|
||
<para>
|
||
Это полезно для определения и абстрагирования функциональности и позволяет
|
||
реализовать дополнительную функциональность в похожих объектах без
|
||
необходимости реализовывать всю общую функциональность.
|
||
</para>
|
||
<para>
|
||
Закрытые методы родительского класса недоступны для дочернего класса. В результате
|
||
дочерние классы могут повторно реализовать закрытый метод без учёта обычных
|
||
правил наследования. Однако до PHP 8.0.0 к закрытым методам применялись ограничения
|
||
<literal>final</literal> и <literal>static</literal>. Начиная с PHP 8.0.0,
|
||
единственное ограничение закрытого метода, которое применяется - это конструкторы <literal>private final</literal>,
|
||
поскольку это обычный способ «отключить» конструктор при использовании вместо него статичных фабричных методов.
|
||
</para>
|
||
<para>
|
||
<link linkend="language.oop5.visibility">Видимость</link> методов,
|
||
свойств и констант можно ослабить, например, <literal>защищённый</literal> метод
|
||
может быть помечен как <literal>общедоступный</literal>, но нельзя ограничить видимость,
|
||
например, нельзя пометить <literal>общедоступное</literal> свойство как <literal>закрытое</literal>.
|
||
Исключением являются конструкторы, видимость которых может быть ограничена,
|
||
например, <literal>общедоступный</literal> конструктор может быть помечен
|
||
как <literal>закрытый</literal> в дочернем классе.
|
||
</para>
|
||
|
||
<note>
|
||
<para>
|
||
Если не используется автозагрузка, классы должны быть объявлены до того, как они
|
||
будут использоваться. Если класс расширяет другой, то родительский класс должен быть
|
||
объявлен до наследующего класса. Это правило применяется к классам, которые наследуют
|
||
другие классы или интерфейсы.
|
||
</para>
|
||
</note>
|
||
<note>
|
||
<para>
|
||
Не разрешается переопределять свойство чтения-записи с помощью <link linkend="language.oop5.properties.readonly-properties">readonly-свойства</link> или наоборот.
|
||
<informalexample>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
class A
|
||
{
|
||
public int $prop;
|
||
}
|
||
|
||
class B extends A
|
||
{
|
||
// Нельзя: read-write -> readonly
|
||
public readonly int $prop;
|
||
}
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</informalexample>
|
||
</para>
|
||
</note>
|
||
|
||
<example>
|
||
<title>Пример наследования</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
|
||
class Foo
|
||
{
|
||
public function printItem($string)
|
||
{
|
||
echo 'Foo: ' . $string . PHP_EOL;
|
||
}
|
||
|
||
public function printPHP()
|
||
{
|
||
echo 'PHP просто супер.' . PHP_EOL;
|
||
}
|
||
}
|
||
|
||
class Bar extends Foo
|
||
{
|
||
public function printItem($string)
|
||
{
|
||
echo 'Bar: ' . $string . PHP_EOL;
|
||
}
|
||
}
|
||
|
||
$foo = new Foo();
|
||
$bar = new Bar();
|
||
$foo->printItem('baz'); // Выведет: 'Foo: baz'
|
||
$foo->printPHP(); // Выведет: 'PHP просто супер'
|
||
$bar->printItem('baz'); // Выведет: 'Bar: baz'
|
||
$bar->printPHP(); // Выведет: 'PHP просто супер'
|
||
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<sect2 xml:id="language.oop5.inheritance.internal-classes">
|
||
<title>Совместимость типов возвращаемых значений с внутренними классами</title>
|
||
|
||
<para>
|
||
До PHP 8.1.0 большинство внутренних классов или методов не объявляли свои типы возвращаемых значений
|
||
и при их расширении допускался любой тип возвращаемого значения.
|
||
</para>
|
||
|
||
<para>
|
||
Начиная с PHP 8.1.0, большинство внутренних методов начали "предварительно" объявлять тип возвращаемого значения.
|
||
В этом случае тип возвращаемого значения методов должен быть совместим с расширяемым родителем;
|
||
в противном случае выдаётся уведомление об устаревании.
|
||
Обратите внимание, что отсутствие явного объявления типа возвращаемого значения также считается несоответствием сигнатуры
|
||
и, соответственно, приводит к уведомлению об устаревании.
|
||
</para>
|
||
|
||
<para>
|
||
Если тип возвращаемого значения не может быть объявлен для переопределяемого метода из-за проблем с совместимостью
|
||
с различными версиями PHP, может быть добавлен атрибут <classname>ReturnTypeWillChange</classname>, чтобы заглушить уведомление об устаревании.
|
||
</para>
|
||
|
||
<example>
|
||
<title>Переопределяющий метод не объявляет никакого типа возвращаемого значения</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
class MyDateTime extends DateTime
|
||
{
|
||
public function modify(string $modifier) { return false; }
|
||
}
|
||
|
||
// "Deprecated: Return type of MyDateTime::modify(string $modifier) should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice", начиная с PHP 8.1.0
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>Переопределяющий метод объявляет неверный тип возвращаемого значения</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
class MyDateTime extends DateTime
|
||
{
|
||
public function modify(string $modifier): ?DateTime { return null; }
|
||
}
|
||
|
||
// "Deprecated: Return type of MyDateTime::modify(string $modifier): ?DateTime should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice", начиная с PHP 8.1.0
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</example>
|
||
|
||
<example>
|
||
<title>Переопределяющий метод объявляет неверный тип возвращаемого значения без уведомления об устаревании</title>
|
||
<programlisting role="php">
|
||
<![CDATA[
|
||
<?php
|
||
class MyDateTime extends DateTime
|
||
{
|
||
/**
|
||
* @return DateTime|false
|
||
*/
|
||
#[\ReturnTypeWillChange]
|
||
public function modify(string $modifier) { return false; }
|
||
}
|
||
|
||
// Уведомление об устаревании не выводится
|
||
?>
|
||
]]>
|
||
</programlisting>
|
||
</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
|
||
-->
|