<?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.traits.php',
    1 => 'Трейты',
    2 => 'Трейты',
  ),
  'up' => 
  array (
    0 => 'language.oop5.php',
    1 => 'Классы и объекты',
  ),
  'prev' => 
  array (
    0 => 'language.oop5.interfaces.php',
    1 => 'Интерфейсы объектов',
  ),
  'next' => 
  array (
    0 => 'language.oop5.anonymous.php',
    1 => 'Анонимные классы',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ru',
    'path' => 'language/oop5/traits.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.oop5.traits" class="sect1">
 <h2 class="title">Трейты</h2>
 <p class="para">
  Способ, которым в языке PHP один и тот же код внедряют в несвязанные иерархии классов,
  называется трейтами (англ. Traits).
 </p>
 <p class="para">
  Трейты — механизм, который разрешает повторно использовать код в языках
  с одиночным наследованием наподобие PHP. Задача трейта —
  уменьшить ограничения одиночного наследования, разрешая разработчику легко
  переиспользовать наборы методов в нескольких независимых классах,
  которые находятся в разных иерархиях наследования. Семантику комбинации трейтов
  и классов определили так, чтобы снизить уровень сложности и избежать
  типичных проблем, свойственных множественному наследованию и примесям (англ. Mixins).
 </p>
 <p class="para">
  Трейт похож на класс, но предназначается только для группировки функциональности
  тонко контролируемым и согласованным образом. Нельзя создать отдельный экземпляр трейта.
  Трейт дополняет традиционное наследование и разрешает выстраивать
  горизонтальную композицию поведения; другими словами, трейт играет роль приложения к членам класса,
  которое не требует наследования.
 </p>

 <div class="example" id="language.oop5.traits.basicexample">
  <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">trait </span><span style="color: #0000BB">TraitA </span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayHello</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Hello'</span><span style="color: #007700">;<br />    }<br />}<br /><br />trait </span><span style="color: #0000BB">TraitB </span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayWorld</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'World'</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">MyHelloWorld<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">TraitA</span><span style="color: #007700">, </span><span style="color: #0000BB">TraitB</span><span style="color: #007700">; </span><span style="color: #FF8000">// Класс разрешает внедрять несколько трейтов<br /><br />    </span><span style="color: #007700">public function </span><span style="color: #0000BB">sayHelloWorld</span><span style="color: #007700">()<br />    {<br />        </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayHello</span><span style="color: #007700">();<br />        echo </span><span style="color: #DD0000">' '</span><span style="color: #007700">;<br /><br />        </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayWorld</span><span style="color: #007700">();<br />        echo </span><span style="color: #DD0000">"!\n"</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$myHelloWorld </span><span style="color: #007700">= new </span><span style="color: #0000BB">MyHelloWorld</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$myHelloWorld</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayHelloWorld</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>
Hello World!
</pre></div>
    </div>
 </div>

 <div class="sect2" id="language.oop5.traits.precedence">
  <h3 class="title">Приоритет</h3>
  <p class="para">
   Член, который класс унаследовал из базового класса, переопределяется членом, который внедрился трейтом.
   Порядок приоритета выстраивается так, что методы трейта переопределяются методами текущего класса,
   а методы, которые класс унаследовал из базового класса, переопределяются методами трейта.
  </p>
  <div class="example" id="language.oop5.traits.precedence.examples.ex1">
   <p><strong>Пример #2 Пример того, в каком порядке выстраивается приоритет</strong></p>
   <div class="example-contents"><p>
    Метод, который класс унаследовал из базового класса, переопределяется методом, который внедрился
    в класс MyHelloWorld из трейта SayWorld. Методы трейта ведут себя как методы
    класса MyHelloWorld. Порядок приоритета такой: методами текущего класса
    переопределяются методы трейта, которыми переопределяются методы
    базового класса.
   </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">Base<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayHello</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Hello '</span><span style="color: #007700">;<br />    }<br />}<br /><br />trait </span><span style="color: #0000BB">SayWorld<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayHello</span><span style="color: #007700">()<br />    {<br />        </span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">sayHello</span><span style="color: #007700">();<br />        echo </span><span style="color: #DD0000">'World!'</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">MyHelloWorld </span><span style="color: #007700">extends </span><span style="color: #0000BB">Base<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">SayWorld</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$o </span><span style="color: #007700">= new </span><span style="color: #0000BB">MyHelloWorld</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$o</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayHello</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>
Hello World!
</pre></div>
   </div>
  </div>
  <div class="example" id="language.oop5.traits.precedence.examples.ex2">
   <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">trait </span><span style="color: #0000BB">HelloWorld<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayHello</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Hello World!'</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">TheWorldIsNotEnough<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">HelloWorld</span><span style="color: #007700">;<br /><br />    public function </span><span style="color: #0000BB">sayHello</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Hello Universe!'</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$o </span><span style="color: #007700">= new </span><span style="color: #0000BB">TheWorldIsNotEnough</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$o</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayHello</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>
Hello Universe!
</pre></div>
   </div>
  </div>
 </div>

 <div class="sect2" id="language.oop5.traits.multiple">
  <h3 class="title">Несколько трейтов</h3>
  <p class="para">
   Названия трейтов перечисляют через запятую в инструкции <code class="literal">use</code>,
   чтобы добавить в класс несколько трейтов.
  </p>
  <div class="example" id="language.oop5.traits.multiple.ex1">
   <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 /><br /></span><span style="color: #007700">trait </span><span style="color: #0000BB">Hello<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayHello</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Hello '</span><span style="color: #007700">;<br />    }<br />}<br /><br />trait </span><span style="color: #0000BB">World<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayWorld</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'World'</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">MyHelloWorld<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">Hello</span><span style="color: #007700">, </span><span style="color: #0000BB">World</span><span style="color: #007700">;<br /><br />    public function </span><span style="color: #0000BB">sayExclamationMark</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'!'</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$o </span><span style="color: #007700">= new </span><span style="color: #0000BB">MyHelloWorld</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$o</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayHello</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$o</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayWorld</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$o</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayExclamationMark</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>
Hello World!
</pre></div>
   </div>
  </div>
 </div>

 <div class="sect2" id="language.oop5.traits.conflict">
  <h3 class="title">Разрешение конфликтов</h3>
  <p class="para">
   При добавлении двумя трейтами метода с одним и тем же названием возникает фатальная
   ошибка, если конфликт явно не разрешили.
  </p>
  <p class="para">
   Оператор <code class="literal">insteadof</code> разрешает конфликты имён и указывает,
   метод какого трейта исключить из класса, когда название метода одного трейта совпадает
   с названием метода другого трейта, который включили в этот же класс.
  </p>
  <p class="para">
   Для добавления псевдонима методу трейта указывают оператор <code class="literal">as</code>,
   поскольку предыдущий оператор только исключает методы.
   Обратите внимание, оператор <code class="literal">as</code>
   не переименовывает метод и не влияет ни на какие другие методы.
  </p>
  <div class="example" id="language.oop5.traits.conflict.ex1">
   <p><strong>Пример #5 Пример разрешения конфликтов</strong></p>
   <div class="example-contents"><p>
    В этом примере в класс Talker включили трейты A и B.
    Поскольку в трейтах A и B содержатся методы, которые вступают в конфликт,
    класс использует вариант метода smallTalk из трейта B, а вариант метода bigTalk из трейта A.
   </p></div>
   <div class="example-contents"><p>
    Оператор <code class="literal">as</code> в классе Aliased_Talker
    разрешает вызывать метод bigTalk трейта B
    по псевдониму <code class="literal">talk</code>.
   </p></div>
   <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: #007700">trait </span><span style="color: #0000BB">A<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">smallTalk</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'a'</span><span style="color: #007700">;<br />    }<br /><br />    public function </span><span style="color: #0000BB">bigTalk</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'A'</span><span style="color: #007700">;<br />    }<br />}<br /><br />trait </span><span style="color: #0000BB">B<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">smallTalk</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'b'</span><span style="color: #007700">;<br />    }<br /><br />    public function </span><span style="color: #0000BB">bigTalk</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'B'</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Talker<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">A</span><span style="color: #007700">, </span><span style="color: #0000BB">B </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">B</span><span style="color: #007700">::</span><span style="color: #0000BB">smallTalk </span><span style="color: #007700">insteadof </span><span style="color: #0000BB">A</span><span style="color: #007700">;<br />        </span><span style="color: #0000BB">A</span><span style="color: #007700">::</span><span style="color: #0000BB">bigTalk </span><span style="color: #007700">insteadof </span><span style="color: #0000BB">B</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Aliased_Talker<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">A</span><span style="color: #007700">, </span><span style="color: #0000BB">B </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">B</span><span style="color: #007700">::</span><span style="color: #0000BB">smallTalk </span><span style="color: #007700">insteadof </span><span style="color: #0000BB">A</span><span style="color: #007700">;<br />        </span><span style="color: #0000BB">A</span><span style="color: #007700">::</span><span style="color: #0000BB">bigTalk </span><span style="color: #007700">insteadof </span><span style="color: #0000BB">B</span><span style="color: #007700">;<br />        </span><span style="color: #0000BB">B</span><span style="color: #007700">::</span><span style="color: #0000BB">bigTalk </span><span style="color: #007700">as </span><span style="color: #0000BB">talk</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </div>

 <div class="sect2" id="language.oop5.traits.visibility">
  <h3 class="title">Изменение видимости метода</h3>
  <p class="para">
   Синтаксис с оператором <code class="literal">as</code> умеет также настраивать
   видимость метода в классе.
  </p>
  <div class="example" id="language.oop5.traits.visibility.ex1">
   <p><strong>Пример #6 Пример изменения видимости метода</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: #007700">trait </span><span style="color: #0000BB">HelloWorld<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayHello</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Привет, мир!'</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #FF8000">// Изменим видимость метода sayHello<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">MyClass1<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">HelloWorld </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">sayHello </span><span style="color: #007700">as protected;<br />    }<br />}<br /><br /></span><span style="color: #FF8000">// Создадим псевдоним метода и изменим видимость этого метода.<br />// Видимость метода sayHello не изменилась<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">MyClass2<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">HelloWorld </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">sayHello </span><span style="color: #007700">as private </span><span style="color: #0000BB">myPrivateHello</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </div>

 <div class="sect2" id="language.oop5.traits.composition">
  <h3 class="title">Импорт трейтов в трейты</h3>
  <p class="para">
   Трейты внедряют не только в классы, но и в другие трейты.
   Трейт возможно скомпоновать из других трейтов путём импорта необходимых трейтов в определении целевого.
   Члены импортированных трейтов становятся частью целевого.
  </p>
  <div class="example" id="language.oop5.traits.composition.ex1">
   <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">trait </span><span style="color: #0000BB">Hello<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayHello</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Hello '</span><span style="color: #007700">;<br />    }<br />}<br /><br />trait </span><span style="color: #0000BB">World<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayWorld</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'World!'</span><span style="color: #007700">;<br />    }<br />}<br /><br />trait </span><span style="color: #0000BB">HelloWorld<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">Hello</span><span style="color: #007700">, </span><span style="color: #0000BB">World</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">MyHelloWorld<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">HelloWorld</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$o </span><span style="color: #007700">= new </span><span style="color: #0000BB">MyHelloWorld</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$o</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayHello</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$o</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sayWorld</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>
Hello World!
</pre></div>
   </div>
  </div>
 </div>

 <div class="sect2" id="language.oop5.traits.abstract">
  <h3 class="title">Абстрактные члены трейтов</h3>
  <p class="para">
   Трейты поддерживают абстрактные методы, чтобы установить требования
   к классу, в который внедрится трейт.
   Поддерживаются общедоступные, защищённые и закрытые методы.
   До PHP 8.0.0 поддерживались только общедоступные и защищённые абстрактные методы.
  </p>
  <div class="caution"><strong class="caution">Предостережение</strong>
   <p class="simpara">
    Начиная с PHP 8.0.0 выдаётся фатальная ошибка, если сигнатура конкретного метода
    не следует <a href="language.oop5.basic.php#language.oop.lsp" class="link">правилам совместимости сигнатур</a>.
    Раньше при несовпадении сигнатуры метода ошибка не выдавалась.
   </p>
  </div>
  <div class="example" id="language.oop5.traits.abstract.ex1">
   <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">trait </span><span style="color: #0000BB">Hello<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">sayHelloWorld</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Hello' </span><span style="color: #007700">. </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getWorld</span><span style="color: #007700">();<br />    }<br /><br />    abstract public function </span><span style="color: #0000BB">getWorld</span><span style="color: #007700">();<br />}<br /><br />class </span><span style="color: #0000BB">MyHelloWorld<br /></span><span style="color: #007700">{<br />    private </span><span style="color: #0000BB">$world</span><span style="color: #007700">;<br /><br />    use </span><span style="color: #0000BB">Hello</span><span style="color: #007700">;<br /><br />    public function </span><span style="color: #0000BB">getWorld</span><span style="color: #007700">()<br />    {<br />        return </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">world</span><span style="color: #007700">;<br />    }<br /><br />    public function </span><span style="color: #0000BB">setWorld</span><span style="color: #007700">(</span><span style="color: #0000BB">$val</span><span style="color: #007700">)<br />    {<br />        </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">world </span><span style="color: #007700">= </span><span style="color: #0000BB">$val</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </div>

 <div class="sect2" id="language.oop5.traits.static">
  <h3 class="title">Статические члены трейта</h3>
  <p class="para">
   В трейтах разрешается определять статические переменные, статические методы и статические свойства.
  </p>
  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    Начиная с PHP 8.1.0 прямой вызов статического метода
    или прямой доступ к статическому свойству в трейте устарели.
    Доступ к статическим методам и свойствам получают только в классе, в который внедрили трейт.
   </p>
  </p></blockquote>
  <div class="example" id="language.oop5.traits.static.ex1">
   <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">trait </span><span style="color: #0000BB">Counter<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">inc</span><span style="color: #007700">()<br />    {<br />        static </span><span style="color: #0000BB">$c </span><span style="color: #007700">= </span><span style="color: #0000BB">0</span><span style="color: #007700">;<br />        </span><span style="color: #0000BB">$c </span><span style="color: #007700">= </span><span style="color: #0000BB">$c </span><span style="color: #007700">+ </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />        echo </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$c</span><span style="color: #DD0000">\n"</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">C1<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">Counter</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">C2<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">Counter</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$o </span><span style="color: #007700">= new </span><span style="color: #0000BB">C1</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$o</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">inc</span><span style="color: #007700">();<br /><br /></span><span style="color: #0000BB">$p </span><span style="color: #007700">= new </span><span style="color: #0000BB">C2</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$p</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">inc</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>
1
1
</pre></div>
    </div>
  </div>
  <div class="example" id="language.oop5.traits.static.ex2">
   <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">trait </span><span style="color: #0000BB">StaticExample<br /></span><span style="color: #007700">{<br />    public static function </span><span style="color: #0000BB">doSomething</span><span style="color: #007700">()<br />    {<br />        return </span><span style="color: #DD0000">'Делаем что-нибудь'</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Example<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">StaticExample</span><span style="color: #007700">;<br />}<br /><br />echo </span><span style="color: #0000BB">Example</span><span style="color: #007700">::</span><span style="color: #0000BB">doSomething</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>
Doing something
</pre></div>
    </div>
  </div>
  <div class="example" id="language.oop5.traits.static.ex3">
   <p><strong>Пример #11 Статические свойства</strong></p>
    <div class="caution"><strong class="caution">Предостережение</strong>
     <p class="simpara">
      До PHP 8.3.0 дочерние классы наследовали статические свойства, которые родительские классы
      получали из трейта, даже если трейт явно внедрялся в дочерний класс.
      Начиная с PHP 8.3.0 статическое свойство трейта переопределяет в дочернем классе статическое свойство,
      которое дочерний класс унаследовал из родительского.
     </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">trait </span><span style="color: #0000BB">T<br /></span><span style="color: #007700">{<br />    public static </span><span style="color: #0000BB">$counter </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">A<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">T</span><span style="color: #007700">;<br /><br />    public static function </span><span style="color: #0000BB">incrementCounter</span><span style="color: #007700">()<br />    {<br />        static::</span><span style="color: #0000BB">$counter</span><span style="color: #007700">++;<br />    }<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 />    use </span><span style="color: #0000BB">T</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">A</span><span style="color: #007700">::</span><span style="color: #0000BB">incrementCounter</span><span style="color: #007700">();<br /><br />echo </span><span style="color: #0000BB">A</span><span style="color: #007700">::</span><span style="color: #0000BB">$counter</span><span style="color: #007700">, </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />echo </span><span style="color: #0000BB">B</span><span style="color: #007700">::</span><span style="color: #0000BB">$counter</span><span style="color: #007700">, </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
  </div>

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

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

 <div class="sect2" id="language.oop5.traits.properties">
  <h3 class="title">Свойства</h3>
  <p class="para">
   В трейтах доступно определение свойств.
  </p>
  <div class="example" id="language.oop5.traits.properties.example">
   <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">trait </span><span style="color: #0000BB">PropertiesTrait<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">$x </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">PropertiesExample<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">PropertiesTrait</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$example </span><span style="color: #007700">= new </span><span style="color: #0000BB">PropertiesExample</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$example</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">x</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="para">
   В классе нельзя определять свойство с названием как у свойства трейта,
   если свойство класса несовместимо со свойством трейта по области видимости и типу,
   модификатору readonly и начальному значению, иначе PHP выдаёт фатальную ошибку.
  </p>
  <div class="example" id="language.oop5.traits.properties.conflicts">
   <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">trait </span><span style="color: #0000BB">PropertiesTrait<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">$same </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br />    public </span><span style="color: #0000BB">$different1 </span><span style="color: #007700">= </span><span style="color: #0000BB">false</span><span style="color: #007700">;<br />    public </span><span style="color: #0000BB">bool $different2</span><span style="color: #007700">;<br />    public </span><span style="color: #0000BB">bool $different3</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">PropertiesExample<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">PropertiesTrait</span><span style="color: #007700">;<br /><br />    public </span><span style="color: #0000BB">$same </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br />    public </span><span style="color: #0000BB">$different1 </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">; </span><span style="color: #FF8000">// Фатальная ошибка<br />    </span><span style="color: #007700">public </span><span style="color: #0000BB">string $different2</span><span style="color: #007700">; </span><span style="color: #FF8000">// Фатальная ошибка<br />    </span><span style="color: #007700">readonly protected </span><span style="color: #0000BB">bool $different3</span><span style="color: #007700">; </span><span style="color: #FF8000">// Фатальная ошибка<br /></span><span style="color: #007700">}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </div>

 <div class="sect2" id="language.oop5.traits.constants">
  <h3 class="title">Константы</h3>
  <p class="para">
   Начиная с версии PHP 8.2.0 в трейтах разрешили также определять константы.
  </p>
  <div class="example" id="language.oop5.traits.constants.example">
   <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">trait </span><span style="color: #0000BB">ConstantsTrait<br /></span><span style="color: #007700">{<br />    public const </span><span style="color: #0000BB">FLAG_MUTABLE </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />    final public const </span><span style="color: #0000BB">FLAG_IMMUTABLE </span><span style="color: #007700">= </span><span style="color: #0000BB">5</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">ConstantsExample<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">ConstantsTrait</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$example </span><span style="color: #007700">= new </span><span style="color: #0000BB">ConstantsExample</span><span style="color: #007700">;<br />echo </span><span style="color: #0000BB">$example</span><span style="color: #007700">::</span><span style="color: #0000BB">FLAG_MUTABLE</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>
1
</pre></div>
    </div>
  </div>
  <p class="para">
   В классе нельзя определять константу с названием как у константы трейта,
   если константа класса несовместима с константой трейта по области видимости,
   начальному значению и модификатору final, иначе PHP выдаёт фатальную ошибку.
  </p>
  <div class="example" id="language.oop5.traits.constants.conflicts">
   <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">trait </span><span style="color: #0000BB">ConstantsTrait<br /></span><span style="color: #007700">{<br />    public const </span><span style="color: #0000BB">FLAG_MUTABLE </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />    final public const </span><span style="color: #0000BB">FLAG_IMMUTABLE </span><span style="color: #007700">= </span><span style="color: #0000BB">5</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">ConstantsExample<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">ConstantsTrait</span><span style="color: #007700">;<br /><br />    public const </span><span style="color: #0000BB">FLAG_IMMUTABLE </span><span style="color: #007700">= </span><span style="color: #0000BB">5</span><span style="color: #007700">; </span><span style="color: #FF8000">// Фатальная ошибка<br /></span><span style="color: #007700">}<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </div>

 <div class="sect2" id="language.oop5.traits.final-methods">
  <h3 class="title">Окончательные методы</h3>
  <p class="simpara">
   Начиная с PHP 8.3.0 методы, которые импортировали из трейтов,
   разрешили делать окончательными через оператор <code class="literal">as</code>
   и модификатор <a href="language.oop5.final.php" class="link">final</a>.
   Определение метода трейта окончательным запрещает дочерним классам
   переопределять метод. Но самому классу, в который импортировали трейт
   и в котором сделали метод окончательным, по-прежнему доступно переопределение метода.
  </p>
  <div class="example" id="language.oop5.traits.final-methods.example">
   <p><strong>Пример #16 
    Определение метода окончательным
    путём добавления модификатора <code class="literal">final</code> при внедрении трейта
   </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">trait </span><span style="color: #0000BB">CommonTrait<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">method</span><span style="color: #007700">()<br />    {<br />        echo </span><span style="color: #DD0000">'Привет'</span><span style="color: #007700">;<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">FinalExampleA<br /></span><span style="color: #007700">{<br />    use </span><span style="color: #0000BB">CommonTrait </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">CommonTrait</span><span style="color: #007700">::</span><span style="color: #0000BB">method </span><span style="color: #007700">as final; </span><span style="color: #FF8000">// Начиная с PHP 8.3.0 модификатор final<br />                                      // запретит переопределять метод в дочерних классах<br />    </span><span style="color: #007700">}<br />}<br /><br />class </span><span style="color: #0000BB">FinalExampleB </span><span style="color: #007700">extends </span><span style="color: #0000BB">FinalExampleA<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">method</span><span style="color: #007700">() {}<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>
Fatal error: Cannot override final method FinalExampleA::method() in ...
</pre></div>
    </div>
  </div>
 </div>

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