<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/language.oop5.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'ru',
  ),
  'this' => 
  array (
    0 => 'language.oop5.inheritance.php',
    1 => 'Наследование',
    2 => 'Наследование',
  ),
  'up' => 
  array (
    0 => 'language.oop5.php',
    1 => 'Классы и объекты',
  ),
  'prev' => 
  array (
    0 => 'language.oop5.visibility.php',
    1 => 'Область видимости',
  ),
  'next' => 
  array (
    0 => 'language.oop5.paamayim-nekudotayim.php',
    1 => 'Оператор разрешения области действия ::',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ru',
    'path' => 'language/oop5/inheritance.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.oop5.inheritance" class="sect1">
  <h2 class="title">Наследование</h2>
  <p class="para">
   Наследование — это хорошо зарекомендовавший себя принцип программирования, и PHP
   использует этот принцип в своей объектной модели. Этот принцип повлияет на то,
   как многие классы и объекты связаны друг с другом.
  </p>
  <p class="para">
   Например, при расширении класса дочерний класс наследует все
   общедоступные и защищённые методы, свойства и константы родительского класса.
   До тех пор пока
   эти методы не будут переопределены, они будут сохранять свою
   исходную функциональность.
  </p>
  <p class="para">
   Это полезно для определения и абстрагирования функциональности и позволяет
   реализовать дополнительную функциональность в похожих объектах без
   необходимости реализовывать всю общую функциональность.
  </p>
  <p class="para">
   Закрытые методы родительского класса недоступны для дочернего класса. В результате
   дочерние классы могут повторно реализовать закрытый метод без учёта обычных
   правил наследования. Однако до PHP 8.0.0 к закрытым методам применялись ограничения
   <code class="literal">final</code> и <code class="literal">static</code>. Начиная с PHP 8.0.0,
   единственное ограничение закрытого метода, которое применяется - это конструкторы <code class="literal">private final</code>,
   поскольку это обычный способ «отключить» конструктор при использовании вместо него статичных фабричных методов.
  </p>
  <p class="para">
   <a href="language.oop5.visibility.php" class="link">Видимость</a> методов,
   свойств и констант можно ослабить, например, <code class="literal">защищённый</code> метод
   может быть помечен как <code class="literal">общедоступный</code>, но нельзя ограничить видимость,
   например, нельзя пометить <code class="literal">общедоступное</code> свойство как <code class="literal">закрытое</code>.
   Исключением являются конструкторы, видимость которых может быть ограничена,
   например, <code class="literal">общедоступный</code> конструктор может быть помечен
   как <code class="literal">закрытый</code> в дочернем классе.
 </p>

  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    Если не используется автозагрузка, классы должны быть объявлены до того, как они
 будут использоваться. Если класс расширяет другой, то родительский класс должен быть
 объявлен до наследующего класса. Это правило применяется к классам, которые наследуют
 другие классы или интерфейсы.
   </p>
  </p></blockquote>
  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    Не разрешается переопределять свойство чтения-записи с помощью <a href="language.oop5.properties.php#language.oop5.properties.readonly-properties" class="link">readonly-свойства</a> или наоборот.
    <div class="informalexample">
     <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">A<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">int $prop</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">B </span><span style="color: #007700">extends </span><span style="color: #0000BB">A<br /></span><span style="color: #007700">{<br />    </span><span style="color: #FF8000">// Нельзя: read-write -&gt; readonly<br />    </span><span style="color: #007700">public readonly </span><span style="color: #0000BB">int $prop</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
  </p></blockquote>

 <div class="example" id="example-1">
  <p><strong>Пример #1 Пример наследования</strong></p>
   <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">Foo<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">printItem</span><span style="color: #007700">(</span><span style="color: #0000BB">$string</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">'Foo: ' </span><span style="color: #007700">. </span><span style="color: #0000BB">$string </span><span style="color: #007700">. </span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br />    }<br /><br />    public function </span><span style="color: #0000BB">printPHP</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'PHP просто супер.' </span><span style="color: #007700">. </span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Bar </span><span style="color: #007700">extends </span><span style="color: #0000BB">Foo<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">printItem</span><span style="color: #007700">(</span><span style="color: #0000BB">$string</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">'Bar: ' </span><span style="color: #007700">. </span><span style="color: #0000BB">$string </span><span style="color: #007700">. </span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$foo </span><span style="color: #007700">= new </span><span style="color: #0000BB">Foo</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$bar </span><span style="color: #007700">= new </span><span style="color: #0000BB">Bar</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$foo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">printItem</span><span style="color: #007700">(</span><span style="color: #DD0000">'baz'</span><span style="color: #007700">); </span><span style="color: #FF8000">// Выведет: 'Foo: baz'<br /></span><span style="color: #0000BB">$foo</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">printPHP</span><span style="color: #007700">();       </span><span style="color: #FF8000">// Выведет: 'PHP просто супер'<br /></span><span style="color: #0000BB">$bar</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">printItem</span><span style="color: #007700">(</span><span style="color: #DD0000">'baz'</span><span style="color: #007700">); </span><span style="color: #FF8000">// Выведет: 'Bar: baz'<br /></span><span style="color: #0000BB">$bar</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">printPHP</span><span style="color: #007700">();       </span><span style="color: #FF8000">// Выведет: 'PHP просто супер'<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
  </div>

 </div>

  <div class="sect2" id="language.oop5.inheritance.internal-classes">
   <h3 class="title">Совместимость типов возвращаемых значений с внутренними классами</h3>

   <p class="para">
    До PHP 8.1.0 большинство внутренних классов или методов не объявляли свои типы возвращаемых значений
    и при их расширении допускался любой тип возвращаемого значения.
   </p>

   <p class="para">
    Начиная с PHP 8.1.0, большинство внутренних методов начали &quot;предварительно&quot; объявлять тип возвращаемого значения.
    В этом случае тип возвращаемого значения методов должен быть совместим с расширяемым родителем;
    в противном случае выдаётся уведомление об устаревании.
    Обратите внимание, что отсутствие явного объявления типа возвращаемого значения также считается несоответствием сигнатуры
    и, соответственно, приводит к уведомлению об устаревании.
   </p>

   <p class="para">
    Если тип возвращаемого значения не может быть объявлен для переопределяемого метода из-за проблем с совместимостью
    с различными версиями PHP, может быть добавлен атрибут <span class="classname"><a href="class.returntypewillchange.php" class="classname">ReturnTypeWillChange</a></span>, чтобы заглушить уведомление об устаревании.
   </p>

   <div class="example" id="example-2">
    <p><strong>Пример #2 Переопределяющий метод не объявляет никакого типа возвращаемого значения</strong></p>
    <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">MyDateTime </span><span style="color: #007700">extends </span><span style="color: #0000BB">DateTime<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">modify</span><span style="color: #007700">(</span><span style="color: #0000BB">string $modifier</span><span style="color: #007700">) { return </span><span style="color: #0000BB">false</span><span style="color: #007700">; }<br />}<br /><br /></span><span style="color: #FF8000">// "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<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>

   <div class="example" id="example-3">
    <p><strong>Пример #3 Переопределяющий метод объявляет неверный тип возвращаемого значения</strong></p>
    <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">MyDateTime </span><span style="color: #007700">extends </span><span style="color: #0000BB">DateTime<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">modify</span><span style="color: #007700">(</span><span style="color: #0000BB">string $modifier</span><span style="color: #007700">): ?</span><span style="color: #0000BB">DateTime </span><span style="color: #007700">{ return </span><span style="color: #0000BB">null</span><span style="color: #007700">; }<br />}<br /><br /></span><span style="color: #FF8000">// "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<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>

   <div class="example" id="example-4">
    <p><strong>Пример #4 Переопределяющий метод объявляет неверный тип возвращаемого значения без уведомления об устаревании</strong></p>
    <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">MyDateTime </span><span style="color: #007700">extends </span><span style="color: #0000BB">DateTime<br /></span><span style="color: #007700">{<br />    </span><span style="color: #FF8000">/**<br />     * @return DateTime|false<br />     */<br />    </span><span style="color: #007700">#[</span><span style="color: #0000BB">\ReturnTypeWillChange</span><span style="color: #007700">]<br />    public function </span><span style="color: #0000BB">modify</span><span style="color: #007700">(</span><span style="color: #0000BB">string $modifier</span><span style="color: #007700">) { return </span><span style="color: #0000BB">false</span><span style="color: #007700">; }<br />}<br /><br /></span><span style="color: #FF8000">// Уведомление об устаревании не выводится<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>

  </div>

 </div><?php manual_footer($setup); ?>