<?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.basic.php',
    1 => 'Основы',
    2 => 'Основы',
  ),
  'up' => 
  array (
    0 => 'language.oop5.php',
    1 => 'Классы и объекты',
  ),
  'prev' => 
  array (
    0 => 'oop5.intro.php',
    1 => 'Введение',
  ),
  'next' => 
  array (
    0 => 'language.oop5.properties.php',
    1 => 'Свойства',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ru',
    'path' => 'language/oop5/basic.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.oop5.basic" class="sect1">
 <h2 class="title">Основы</h2>

 <div class="sect2" id="language.oop5.basic.class">
  <h3 class="title">class</h3>
  <p class="para">
   Каждое определение класса начинается с ключевого слова <code class="literal">class</code>, затем
   идёт имя класса, а потом пара фигурных скобок, в которых определяют
   свойства и методы класса.
  </p>
  <p class="para">
   Для класса разрешается выбирать произвольное название, при условии,
   что это не <a href="reserved.php" class="link">зарезервированное слово</a> языка PHP.
   Начиная с PHP 8.4.0 объявление названия класса, которое состоит из одного символа подчёркивания <code class="literal">_</code>,
   устарело.
   Допустимое название класса начинается с буквы или подчеркивания,
   за которым идёт произвольное количество букв, цифр или символов подчеркивания.
   В виде регулярного выражения правило именования классов выглядят так:
   <code class="code">^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$</code>.
  </p>
  <p class="para">
   Классы содержат <a href="language.oop5.constants.php" class="link">константы</a>,
   <a href="language.oop5.properties.php" class="link">переменные</a>, которые в классах
   называют свойствами, и функции, которые в классах называют методами.
  </p>
  <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">SimpleClass<br /></span><span style="color: #007700">{<br />    </span><span style="color: #FF8000">// Объявление свойства<br />    </span><span style="color: #007700">public </span><span style="color: #0000BB">$var </span><span style="color: #007700">= </span><span style="color: #DD0000">'значение по умолчанию'</span><span style="color: #007700">;<br /><br />    </span><span style="color: #FF8000">// Объявление метода<br />    </span><span style="color: #007700">public function </span><span style="color: #0000BB">displayVar</span><span style="color: #007700">() {<br />        echo </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">var</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="para">
   Псевдопеременная <var class="varname">$this</var> доступна,
   когда метод вызывается из контекста объекта.
   Переменная <var class="varname">$this</var> — значение вызывающего объекта.
  </p>
  <div class="warning"><strong class="warning">Внимание</strong>
   <p class="para">
    Вызов нестатического метода статически выбрасывает исключение <span class="classname"><a href="class.error.php" class="classname">Error</a></span>.
    До PHP 8.0.0 это приводило к уведомлению об устаревании,
    а переменная <var class="varname">$this</var> оставалась неопределённой.
   </p>
   <div class="example" id="language.oop5.basic.class.this">
    <p><strong>Пример #2 Примеры псевдопеременной <var class="varname">$this</var></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">A<br /></span><span style="color: #007700">{<br />    function </span><span style="color: #0000BB">foo</span><span style="color: #007700">()<br />    {<br />        if (isset(</span><span style="color: #0000BB">$this</span><span style="color: #007700">)) {<br />            echo </span><span style="color: #DD0000">'PHP определил переменную $this ('</span><span style="color: #007700">;<br />            echo </span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">);<br />            echo </span><span style="color: #DD0000">")\n"</span><span style="color: #007700">;<br />        } else {<br />            echo </span><span style="color: #DD0000">"PHP не определил переменную \$this.\n"</span><span style="color: #007700">;<br />        }<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">B<br /></span><span style="color: #007700">{<br />    function </span><span style="color: #0000BB">bar</span><span style="color: #007700">()<br />    {<br />        </span><span style="color: #0000BB">A</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">();<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$a </span><span style="color: #007700">= new </span><span style="color: #0000BB">A</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$a</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">A</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$b </span><span style="color: #007700">= new </span><span style="color: #0000BB">B</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$b</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bar</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">B</span><span style="color: #007700">::</span><span style="color: #0000BB">bar</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     
<div class="example-contents"><p>
 Результат выполнения приведённого примера в PHP 7:
</p></div>

     <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
PHP определил переменную $this (A)

Deprecated: Non-static method A::foo() should not be called statically in %s  on line 27
PHP не определил переменную $this.

Deprecated: Non-static method A::foo() should not be called statically in %s  on line 20
PHP не определил переменную $this.

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
PHP не определил переменную $this.
</pre></div>
     </div>
     
<div class="example-contents"><p>
 Результат выполнения приведённого примера в PHP 8:
</p></div>

     <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
PHP определил переменную $this (A)

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
</pre></div>
     </div>
   </div>
  </div>

  <div class="sect3" id="language.oop5.basic.class.readonly">
   <h4 class="title">Классы только для чтения</h4>
   <p class="para">
    Начиная с PHP 8.2.0 класс можно пометить
    модификатором <span class="modifier">readonly</span>.
    Пометка класса как <span class="modifier">readonly</span> добавит
    <a href="language.oop5.properties.php#language.oop5.properties.readonly-properties" class="link">модификатор <span class="modifier">readonly</span></a>
    к каждому объявленному свойству и не разрешит создавать
    <a href="language.oop5.properties.php#language.oop5.properties.dynamic-properties" class="link">динамические свойства</a>.
    Поддержку динамических свойств невозможно добавить даже атрибутом
    <span class="classname"><a href="class.allowdynamicproperties.php" class="classname">AllowDynamicProperties</a></span>. Попытка это сделать вызовет ошибку компиляции.
   </p>
   <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">#[</span><span style="color: #0000BB">\AllowDynamicProperties</span><span style="color: #007700">]<br />readonly class </span><span style="color: #0000BB">Foo </span><span style="color: #007700">{}<br /><br /></span><span style="color: #FF8000">// Fatal error: Cannot apply #[AllowDynamicProperties] to readonly class Foo<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>

   <p class="para">
    В классах только для чтения нельзя объявлять нетипизированные и статические свойства,
    поскольку такие свойства нельзя помечать модификатором <code class="literal">readonly</code>:
   </p>
   <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">readonly class </span><span style="color: #0000BB">Foo<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">$bar</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #FF8000">// Fatal error: Readonly property Foo::$bar must have type<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    <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">readonly class </span><span style="color: #0000BB">Foo<br /></span><span style="color: #007700">{<br />    public static </span><span style="color: #0000BB">int $bar</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #FF8000">// Fatal error: Readonly class Foo cannot declare static properties<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>
   <p class="para">
    Класс <span class="modifier">readonly</span> получится
    <a href="language.oop5.basic.php#language.oop5.basic.extends" class="link">расширить</a>
    тогда и только тогда, когда дочерний класс
    тоже <span class="modifier">readonly</span>-класс.
   </p>
  </div>

 </div>

 <div class="sect2" id="language.oop5.basic.new">
  <h3 class="title">Ключевое слово new</h3>
  <p class="para">
   Экземпляр класса создаётся директивой <code class="literal">new</code>.
   Новый объект создаётся, если только
   <a href="language.oop5.decon.php" class="link">конструктор</a> объекта
   во время ошибки не выбрасывает <a href="language.exceptions.php" class="link">исключение</a>.
   Класс рекомендуют определять перед тем, как создавать экземпляр класса;
   иногда это обязательное требование.
  </p>
  <p class="para">
   PHP создаст новый экземпляр класса, если с ключевым словом
   <code class="literal">new</code> указали переменную, которая содержит строку (<span class="type"><a href="language.types.string.php" class="type string">string</a></span>)
   с названием класса.
   Чтобы создать экземпляр класса, который определили в пространстве имён,
   требуется указывать абсолютное имя класса.
  </p>

  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    Круглые скобки после названия класса разрешается опускать,
    если нет аргументов, которые требуется передать в конструктор класса.
   </p>
  </p></blockquote>

  <div class="example" id="example-2">
   <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 /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">SimpleClass </span><span style="color: #007700">{}<br /><br /></span><span style="color: #0000BB">$instance </span><span style="color: #007700">= new </span><span style="color: #0000BB">SimpleClass</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$instance</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// Или создаём экземпляр класса через переменную:<br /></span><span style="color: #0000BB">$className </span><span style="color: #007700">= </span><span style="color: #DD0000">'SimpleClass'</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$instance </span><span style="color: #007700">= new </span><span style="color: #0000BB">$className</span><span style="color: #007700">(); </span><span style="color: #FF8000">// Аналогично new SimpleClass()<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$instance</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="para">
   С PHP 8.0.0 поддерживается ключевое слово
   <code class="literal">new</code> с произвольными выражениями.
   Это разрешает создавать более сложные экземпляры, если
   выражение создаёт строку (<span class="type"><a href="language.types.string.php" class="type string">string</a></span>).
   Выражения берут в круглые скобки.
   </p>
   <div class="example" id="example-3">
    <p><strong>Пример #4 Пример новых объектов, которые создали через произвольные выражения</strong></p>
    <div class="example-contents"><p>
     Пример показывает варианты допустимых произвольных выражений, которые представляют имя класса.
     Пример вызова функции, конкатенации строк и константы <strong><code>::class</code></strong>.
    </p></div>
    <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">ClassA </span><span style="color: #007700">extends </span><span style="color: #0000BB">\stdClass </span><span style="color: #007700">{}<br />class </span><span style="color: #0000BB">ClassB </span><span style="color: #007700">extends </span><span style="color: #0000BB">\stdClass </span><span style="color: #007700">{}<br />class </span><span style="color: #0000BB">ClassC </span><span style="color: #007700">extends </span><span style="color: #0000BB">ClassB </span><span style="color: #007700">{}<br />class </span><span style="color: #0000BB">ClassD </span><span style="color: #007700">extends </span><span style="color: #0000BB">ClassA </span><span style="color: #007700">{}<br /><br />function </span><span style="color: #0000BB">getSomeClass</span><span style="color: #007700">(): </span><span style="color: #0000BB">string<br /></span><span style="color: #007700">{<br />    return </span><span style="color: #DD0000">'ClassA'</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(new (</span><span style="color: #0000BB">getSomeClass</span><span style="color: #007700">()));<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(new (</span><span style="color: #DD0000">'Class' </span><span style="color: #007700">. </span><span style="color: #DD0000">'B'</span><span style="color: #007700">));<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(new (</span><span style="color: #DD0000">'Class' </span><span style="color: #007700">. </span><span style="color: #DD0000">'C'</span><span style="color: #007700">));<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(new (</span><span style="color: #0000BB">ClassD</span><span style="color: #007700">::class));<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    
<div class="example-contents"><p>
 Результат выполнения приведённого примера в PHP 8:
</p></div>

    <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
object(ClassA)#1 (0) {
}
object(ClassB)#1 (0) {
}
object(ClassC)#1 (0) {
}
object(ClassD)#1 (0) {
}

</pre></div>
    </div>
   </div>
  <p class="para">
   В контексте класса возможно создать новый объект
   выражениями <code class="literal">new self</code> и <code class="literal">new parent</code>.
  </p>
  <p class="para">
   Переменная получит доступ к тому же экземпляру класса, что и объект,
   который присвоили переменной.
   Такое же поведение наблюдается при передаче экземпляра класса в функцию.
   Копию объекта создают <a href="language.oop5.cloning.php" class="link">клонированием</a>.
  </p>
  <div class="example" id="example-4">
   <p><strong>Пример #5 Присваивание объекта</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">SimpleClass<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">string $var</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$instance </span><span style="color: #007700">= new </span><span style="color: #0000BB">SimpleClass</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$assigned   </span><span style="color: #007700">=  </span><span style="color: #0000BB">$instance</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$reference  </span><span style="color: #007700">=&amp; </span><span style="color: #0000BB">$instance</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$instance</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">var </span><span style="color: #007700">= </span><span style="color: #DD0000">'У экземпляра класса, на который ссылается переменная $assigned, тоже будет это значение'</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$instance </span><span style="color: #007700">= </span><span style="color: #0000BB">null</span><span style="color: #007700">; </span><span style="color: #FF8000">// Значения переменных $instance и $reference станут равны null<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$instance</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$reference</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$assigned</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

    <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
NULL
NULL
object(SimpleClass)#1 (1) {
  [&quot;var&quot;]=&gt;
  string(152) &quot;У экземпляра класса, на который ссылается переменная $assigned, тоже будет это значение&quot;
}
</pre></div>
    </div>
  </div>
  <p class="para">
   Экземпляры объектов создают несколькими способами:
  </p>
  <div class="example" id="example-5">
   <p><strong>Пример #6 Новые объекты</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">Test<br /></span><span style="color: #007700">{<br />    public static function </span><span style="color: #0000BB">getNew</span><span style="color: #007700">()<br />    {<br />        return new static();<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Child </span><span style="color: #007700">extends </span><span style="color: #0000BB">Test </span><span style="color: #007700">{}<br /><br /></span><span style="color: #0000BB">$obj1 </span><span style="color: #007700">= new </span><span style="color: #0000BB">Test</span><span style="color: #007700">(); </span><span style="color: #FF8000">// По имени класса<br /></span><span style="color: #0000BB">$obj2 </span><span style="color: #007700">= new </span><span style="color: #0000BB">$obj1</span><span style="color: #007700">(); </span><span style="color: #FF8000">// Через переменную, которая содержит объект<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$obj1 </span><span style="color: #007700">!== </span><span style="color: #0000BB">$obj2</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$obj3 </span><span style="color: #007700">= </span><span style="color: #0000BB">Test</span><span style="color: #007700">::</span><span style="color: #0000BB">getNew</span><span style="color: #007700">(); </span><span style="color: #FF8000">// Через метод класса<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$obj3 </span><span style="color: #007700">instanceof </span><span style="color: #0000BB">Test</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$obj4 </span><span style="color: #007700">= </span><span style="color: #0000BB">Child</span><span style="color: #007700">::</span><span style="color: #0000BB">getNew</span><span style="color: #007700">(); </span><span style="color: #FF8000">// Через метод класса-наследника<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$obj4 </span><span style="color: #007700">instanceof </span><span style="color: #0000BB">Child</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

    <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
bool(true)
bool(true)
bool(true)
</pre></div>
    </div>
  </div>
  <p class="para">
   К свойству или методу только что созданного объекта получится
   обратиться одним выражением:
  </p>
  <div class="example" id="example-6">
   <p><strong>Пример #7 Доступ к свойствам и методам только что созданного объекта</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">echo (new </span><span style="color: #0000BB">DateTime</span><span style="color: #007700">())-&gt;</span><span style="color: #0000BB">format</span><span style="color: #007700">(</span><span style="color: #DD0000">'Y'</span><span style="color: #007700">), </span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br /><br /></span><span style="color: #FF8000">// Начиная с PHP 8.4.0 брать в скобки выражение new не обязательно<br /></span><span style="color: #007700">echo new </span><span style="color: #0000BB">DateTime</span><span style="color: #007700">()-&gt;</span><span style="color: #0000BB">format</span><span style="color: #007700">(</span><span style="color: #DD0000">'Y'</span><span style="color: #007700">), </span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    
<div class="example-contents"><p>
 Вывод приведённого примера будет похож на:
</p></div>

    <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
2025
2025
</pre></div>
    </div>
  </div>

  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <span class="simpara">
    До PHP 7.1 язык не вычислял значения аргументов
    в круглых скобках выражения, которым инстанциировали объект класса,
    если в классе не было метода-конструктора.
   </span>
  </p></blockquote>
 </div>
 <div class="sect2" id="language.oop5.basic.properties-methods">
  <h3 class="title">Свойства и методы</h3>
  <p class="para">
   Свойства и методы класса живут в отдельных «пространствах имён»,
   поэтому свойства и методы допустимо называть одинаково.
   У ссылок на свойства и методы одинаковая нотация, и получит
   ли код доступ к свойству или вызовет метод — зависит только от контекста,
   т. е. обращаются ли к переменной или вызывают функцию.
  </p>
  <div class="example" id="example-7">
   <p><strong>Пример #8 Сравнение доступа к свойству и вызова метода</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 </span><span style="color: #0000BB">$bar </span><span style="color: #007700">= </span><span style="color: #DD0000">'свойство'</span><span style="color: #007700">;<br /><br />    public function </span><span style="color: #0000BB">bar</span><span style="color: #007700">()<br />    {<br />        return </span><span style="color: #DD0000">'метод'</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$obj </span><span style="color: #007700">= new </span><span style="color: #0000BB">Foo</span><span style="color: #007700">();<br />echo </span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bar</span><span style="color: #007700">, </span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">, </span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bar</span><span style="color: #007700">(), </span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

   
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

   <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
свойство
метод
</pre></div>
   </div>
  </div>
  <p class="para">
   Из-за одинаковой нотации прямой вызов <a href="functions.anonymous.php" class="link">анонимной
   функции</a>, которую присвоили переменной, невозможен.
   Вместо этого свойство вначале присваивают переменной, например.
   Вызвать же анонимную функцию, которую сохранили в свойстве класса, напрямую получится,
   если взять свойство в круглые скобки.
  </p>
  <div class="example" id="example-8">
   <p><strong>Пример #9 Вызов анонимной функции, которую содержит свойство</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 </span><span style="color: #0000BB">$bar</span><span style="color: #007700">;<br /><br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">()<br />    {<br />        </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bar </span><span style="color: #007700">= function() {<br />            return </span><span style="color: #0000BB">42</span><span style="color: #007700">;<br />        };<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$obj </span><span style="color: #007700">= new </span><span style="color: #0000BB">Foo</span><span style="color: #007700">();<br /><br />echo (</span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">bar</span><span style="color: #007700">)(), </span><span style="color: #0000BB">PHP_EOL</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

    <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
42
</pre></div>
    </div>
  </div>
 </div>
 <div class="sect2" id="language.oop5.basic.extends">
  
  
  <h3 class="title">Ключевое слово extends</h3>
  <p class="para">
   Класс умеет наследовать константы, методы и свойства другого класса через
   ключевое слово <code class="literal">extends</code> в объявлении класса.
   Невозможно наследовать больше одного класса, одному классу разрешено
   наследовать только один базовый класс.
  </p>
  <p class="para">
   Константы, методы и свойства, которые унаследовал класс, разрешается переопределять
   в дочернем классе путём повторного объявления с таким же именем, которое определили
   в родительском классе.
   Метод или константу нельзя переопределить, если в родительском классе метод
   или константу определили окончательными — с ключевым словом
   <a href="language.oop5.final.php" class="link">final</a>.
   Доступ к переопределённым методам или статическим свойствам родительского класса
   получают, когда ссылаются на них через
   <a href="language.oop5.paamayim-nekudotayim.php" class="link">parent::</a>.
  </p>
   <blockquote class="note"><p><strong class="note">Замечание</strong>: 
    <span class="simpara">
     С PHP 8.1.0 разрешается объявлять константы окончательными.
    </span>
   </p></blockquote>
  <div class="example" id="example-9">
   <p><strong>Пример #10 Простое наследование классов</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">SimpleClass<br /></span><span style="color: #007700">{<br />    function </span><span style="color: #0000BB">displayVar</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">"Родительский класс\n"</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">ExtendClass </span><span style="color: #007700">extends </span><span style="color: #0000BB">SimpleClass<br /></span><span style="color: #007700">{<br />    </span><span style="color: #FF8000">// Переопределение родительского метода<br />    </span><span style="color: #007700">function </span><span style="color: #0000BB">displayVar</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">"Дочерний класс\n"</span><span style="color: #007700">;<br />        </span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">displayVar</span><span style="color: #007700">();<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$extended </span><span style="color: #007700">= new </span><span style="color: #0000BB">ExtendClass</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$extended</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">displayVar</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

   
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

   <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
Дочерний класс
Родительский класс
</pre></div>
   </div>
  </div>

  <div class="sect3" id="language.oop.lsp">
    <h4 class="title">Правила совместимости сигнатур</h4>
    <p class="para">
     При переопределении метода сигнатура метода должна быть совместима
     с родительским методом.
     В противном случае PHP выдаст фатальную ошибку или, до PHP 8.0.0,
     сгенерирует ошибку уровня <strong><code><a href="errorfunc.constants.php#constant.e-warning">E_WARNING</a></code></strong>.
     Сигнатура совместима, если она соответствует правилам
     <a href="language.oop5.variance.php" class="link">вариантности</a>,
     делает обязательный параметр необязательным, добавляет только необязательные
     новые параметры и не ограничивает, а только ослабляет видимость.
     Эти правила называются принципом подстановки Барбары Лисков, или сокращённо LSP.
     Правила совместимости не распространяются
     <a href="language.oop5.decon.php#language.oop5.decon.constructor" class="link">на конструктор</a>
     и сигнатуру <code class="literal">private</code>-методов, и поэтому они не выдадут
     фатальную ошибку, если сигнатура не соответствует.
    </p>
    <div class="example" id="example-10">
     <p><strong>Пример #11 Совместимость дочерних методов</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">Base<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">int $a</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">"Допустимо\n"</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Extend1 </span><span style="color: #007700">extends </span><span style="color: #0000BB">Base<br /></span><span style="color: #007700">{<br />    function </span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">int $a </span><span style="color: #007700">= </span><span style="color: #0000BB">5</span><span style="color: #007700">)<br />    {<br />        </span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">);<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Extend2 </span><span style="color: #007700">extends </span><span style="color: #0000BB">Base<br /></span><span style="color: #007700">{<br />    function </span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">int $a</span><span style="color: #007700">, </span><span style="color: #0000BB">$b </span><span style="color: #007700">= </span><span style="color: #0000BB">5</span><span style="color: #007700">)<br />    {<br />        </span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">);<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$extended1 </span><span style="color: #007700">= new </span><span style="color: #0000BB">Extend1</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$extended1</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$extended2 </span><span style="color: #007700">= new </span><span style="color: #0000BB">Extend2</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$extended2</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

     <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
Допустимо
Допустимо
</pre></div>
     </div>
    </div>

    <p class="para">
     На следующих примерах видно, что дочерний метод, который
     удаляет параметр или делает необязательный
     параметр обязательным, несовместим с родительским методом.
    </p>
    <div class="example" id="example-11">
     <p><strong>Пример #12 Фатальная ошибка, когда дочерний метод удаляет параметр</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">Base<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">int $a </span><span style="color: #007700">= </span><span style="color: #0000BB">5</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">"Допустимо\n"</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Extend </span><span style="color: #007700">extends </span><span style="color: #0000BB">Base<br /></span><span style="color: #007700">{<br />    function </span><span style="color: #0000BB">foo</span><span style="color: #007700">()<br />    {<br />        </span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">);<br />    }<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     
<div class="example-contents"><p>
 Результат выполнения приведённого примера в PHP 8 аналогичен:
</p></div>

     <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
Fatal error: Declaration of Extend::foo() must be compatible with Base::foo(int $a = 5) in /in/evtlq on line 13
</pre></div>
     </div>
    </div>
    <div class="example" id="example-12">
     <p><strong>Пример #13 
      Фатальная ошибка, когда дочерний метод делает необязательный параметр обязательным
     </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">Base<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">int $a </span><span style="color: #007700">= </span><span style="color: #0000BB">5</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">"Допустимо\n"</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Extend </span><span style="color: #007700">extends </span><span style="color: #0000BB">Base<br /></span><span style="color: #007700">{<br />    function </span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">int $a</span><span style="color: #007700">)<br />    {<br />        </span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">foo</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">);<br />    }<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     
<div class="example-contents"><p>
 Результат выполнения приведённого примера в PHP 8 аналогичен:
</p></div>

     <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
Fatal error: Declaration of Extend::foo(int $a) must be compatible with Base::foo(int $a = 5) in /in/qJXVC on line 13
</pre></div>
     </div>
    </div>

    <div class="warning"><strong class="warning">Внимание</strong>
     <p class="para">
      Переименование параметра метода в дочернем классе не относится
      к несовместимости сигнатуры. Однако это не рекомендуется, поскольку
      приведёт к исключению <span class="classname"><a href="class.error.php" class="classname">Error</a></span> во время выполнения,
      если передавать
      <a href="functions.arguments.php#functions.named-arguments" class="link">именованные аргументы</a>.
     </p>
     <div class="example" id="example-13">
      <p><strong>Пример #14 
       Ошибка передачи именованных аргументов в параметры, которые переименовали
       в дочернем классе
      </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">A<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">$foo</span><span style="color: #007700">, </span><span style="color: #0000BB">$bar</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 />    public function </span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">$a</span><span style="color: #007700">, </span><span style="color: #0000BB">$b</span><span style="color: #007700">) {}<br />}<br /><br /></span><span style="color: #0000BB">$obj </span><span style="color: #007700">= new </span><span style="color: #0000BB">B</span><span style="color: #007700">();<br /><br /></span><span style="color: #FF8000">// Передача параметров согласно контракту метода A::test()<br /></span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">test</span><span style="color: #007700">(</span><span style="color: #0000BB">foo</span><span style="color: #007700">: </span><span style="color: #DD0000">"foo"</span><span style="color: #007700">, </span><span style="color: #0000BB">bar</span><span style="color: #007700">: </span><span style="color: #DD0000">"bar"</span><span style="color: #007700">); </span><span style="color: #FF8000">// ОШИБКА!<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
      </div>

      
<div class="example-contents"><p>
 Вывод приведённого примера будет похож на:
</p></div>

      <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
Fatal error: Uncaught Error: Unknown named parameter $foo in /in/XaaeN:14
Stack trace:
#0 {main}
  thrown in /in/XaaeN on line 14
</pre></div>
      </div>
     </div>
    </div>
   </div>
 </div>

 <div class="sect2" id="language.oop5.basic.class.class">
  <h3 class="title">Константа ::class</h3>

  <p class="para">
   Ключевым словом <code class="literal">class</code> также разрешают имя класса.
   Запись <code class="literal">ClassName::class</code> вернёт
   абсолютное имя класса <code class="literal">ClassName</code>.
   Это полезно при работе с классами, которые определили
   <a href="language.namespaces.php" class="link">в пространстве имён</a>.
  </p>
  <p class="para">
   <div class="example" id="language.oop5.basic.class.class.name">
    <p><strong>Пример #15 Разрешение имени класса</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">namespace </span><span style="color: #0000BB">NS </span><span style="color: #007700">{<br />    class </span><span style="color: #0000BB">ClassName </span><span style="color: #007700">{}<br /><br />    echo </span><span style="color: #0000BB">ClassName</span><span style="color: #007700">::class;<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

    <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
NS\ClassName
</pre></div>
    </div>
   </div>
  </p>
  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    Разрешение имени класса через конструкцию <code class="literal">::class</code> —
    преобразование во время компиляции. Это означает, что в момент, когда
    компилятор создаёт строку с именем класса, PHP ещё не выполнил
    автозагрузку класса. Следствием этого становится то, что имена
    классов разворачиваются, даже если класс не существует. При этом
    ошибку PHP не выдаёт.
   </p>
   <div class="example" id="language.oop5.basic.class.class.fail">
    <p><strong>Пример #16 Разрешение имени несуществующего класса</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">print </span><span style="color: #0000BB">Does\Not\Exist</span><span style="color: #007700">::class;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

     
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

     <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
Does\Not\Exist
</pre></div>
     </div>
    </div>
  </p></blockquote>
  <p class="para">
   Начиная с PHP 8.0.0 константа <code class="literal">::class</code> научилась разрешать
   имена объектов. Это разрешение константа совершает при выполнении кода, а компиляции.
   Результат аналогичен вызову функции <span class="function"><a href="function.get-class.php" class="function">get_class()</a></span> на объекте.
  </p>
  <div class="example" id="language.oop5.basic.class.class.object">
   <p><strong>Пример #17 Разрешение имени объекта</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">namespace </span><span style="color: #0000BB">NS </span><span style="color: #007700">{<br />    class </span><span style="color: #0000BB">ClassName </span><span style="color: #007700">{}<br /><br />    </span><span style="color: #0000BB">$c </span><span style="color: #007700">= new </span><span style="color: #0000BB">ClassName</span><span style="color: #007700">();<br />    print </span><span style="color: #0000BB">$c</span><span style="color: #007700">::class;<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

    
<div class="example-contents"><p>
 Результат выполнения приведённого примера:
</p></div>

    <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
NS\ClassName
</pre></div>
    </div>
  </div>
 </div>
 <div class="sect2" id="language.oop5.basic.nullsafe">
  <h3 class="title">Null-безопасные методы и свойства</h3>
  <p class="para">
   Оператор nullsafe появился в PHP 8.0.0 и разрешил безопасно
   обращаться к свойствам и методам: <code class="literal">?-&gt;</code>.
   Null-безопасный оператор работает аналогично доступу к свойству или методу,
   как описывали предыдущие параграфы,
   за исключением возврата значения <strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong> вместо генерации исключения,
   когда разыменовываемый объект равен <strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong>; PHP пропустит остаток цепочки обращений,
   если разыменование в цепочке получит значение <strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong>.
  </p>
  <p class="para">
   Результат аналогичен предварительному оборачиванию каждого обращения
   в функцию <span class="function"><a href="function.is-null.php" class="function">is_null()</a></span>, но более компактный.
  </p>
  <p class="para">
   <div class="example" id="example-14">
    <p><strong>Пример #18 Пример работы Nullsafe-оператора</strong></p>
    <div class="example-contents">
<div class="annotation-non-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// Начиная с PHP 8.0.0 эта строка:<br /></span><span style="color: #0000BB">$result </span><span style="color: #007700">= </span><span style="color: #0000BB">$repository</span><span style="color: #007700">?-&gt;</span><span style="color: #0000BB">getUser</span><span style="color: #007700">(</span><span style="color: #0000BB">5</span><span style="color: #007700">)?-&gt;</span><span style="color: #0000BB">name</span><span style="color: #007700">;<br /><br /></span><span style="color: #FF8000">// эквивалентна следующему блоку кода:<br /></span><span style="color: #007700">if (</span><span style="color: #0000BB">is_null</span><span style="color: #007700">(</span><span style="color: #0000BB">$repository</span><span style="color: #007700">)) {<br />    </span><span style="color: #0000BB">$result </span><span style="color: #007700">= </span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />} else {<br />    </span><span style="color: #0000BB">$user </span><span style="color: #007700">= </span><span style="color: #0000BB">$repository</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getUser</span><span style="color: #007700">(</span><span style="color: #0000BB">5</span><span style="color: #007700">);<br /><br />    if (</span><span style="color: #0000BB">is_null</span><span style="color: #007700">(</span><span style="color: #0000BB">$user</span><span style="color: #007700">)) {<br />        </span><span style="color: #0000BB">$result </span><span style="color: #007700">= </span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />    } else {<br />        </span><span style="color: #0000BB">$result </span><span style="color: #007700">= </span><span style="color: #0000BB">$user</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">name</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>
  </p>
  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    Оператором nullsafe лучше пользоваться, когда null рассматривается
    как допустимое значение, которое, как ожидается, вернут свойство
    или метод. Для указания на ошибку лучше выбрасывать исключение.
   </p>
  </p></blockquote>
 </div>
</div><?php manual_footer($setup); ?>