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

contributors($setup);

?>
<div id="language.oop5.overloading" class="sect1">
 <h2 class="title">Перегрузка</h2>

 <p class="para">
  Перегрузка в PHP означает возможность динамически <q class="quote">создавать</q>
  свойства и методы. Эти динамические сущности обрабатываются с
  помощью магических методов, которые можно создать в классе для
  различных видов действий.
 </p>

 <p class="para">
  Методы перегрузки вызываются при взаимодействии со свойствами
  или методами, которые не были объявлены или не <a href="language.oop5.visibility.php" class="link">видны</a> в текущей области
  видимости. Далее в этом разделе будут использоваться термины
  <q class="quote">недоступные свойства</q> или <q class="quote">недоступные методы</q>
  для обозначения этой комбинации объявления и области видимости.
 </p>

 <p class="para">
  Все методы перегрузки должны быть объявлены как <code class="literal">public</code>.
 </p>

 <blockquote class="note"><p><strong class="note">Замечание</strong>: 
  <p class="para">
   Ни один из аргументов этих магических методов не может быть передан
   <a href="functions.arguments.php#functions.arguments.by-reference" class="link">по ссылке</a>.
  </p>
 </p></blockquote>

 <blockquote class="note"><p><strong class="note">Замечание</strong>: 
  <p class="para">
   Интерпретация <q class="quote">перегрузки</q> в PHP отличается
   от большинства объектно-ориентированных языков. Традиционно
   перегрузка означает возможность иметь несколько одноимённых методов
   с разным количеством и типами аргументов.
  </p>
 </p></blockquote>

 <div class="sect2" id="language.oop5.overloading.members">
  <h3 class="title">Перегрузка свойств</h3>

  <div class="methodsynopsis dc-description" id="object.set">
   <span class="modifier">public</span> <span class="methodname"><strong>__set</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.string.php" class="type string">string</a></span> <code class="parameter">$name</code></span>, <span class="methodparam"><span class="type"><a href="language.types.mixed.php" class="type mixed">mixed</a></span> <code class="parameter">$value</code></span>): <span class="type"><a href="language.types.void.php" class="type void">void</a></span></div>

  <div class="methodsynopsis dc-description" id="object.get"><span class="modifier">public</span> <span class="methodname"><strong>__get</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.string.php" class="type string">string</a></span> <code class="parameter">$name</code></span>): <span class="type"><a href="language.types.mixed.php" class="type mixed">mixed</a></span></div>

  <div class="methodsynopsis dc-description" id="object.isset"><span class="modifier">public</span> <span class="methodname"><strong>__isset</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.string.php" class="type string">string</a></span> <code class="parameter">$name</code></span>): <span class="type"><a href="language.types.boolean.php" class="type bool">bool</a></span></div>

  <div class="methodsynopsis dc-description" id="object.unset"><span class="modifier">public</span> <span class="methodname"><strong>__unset</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.string.php" class="type string">string</a></span> <code class="parameter">$name</code></span>): <span class="type"><a href="language.types.void.php" class="type void">void</a></span></div>


  <p class="para">
   Метод <a href="language.oop5.overloading.php#object.set" class="link">__set()</a> будет выполнен при записи
   данных в недоступные (защищённые или приватные) или несуществующие свойства.
  </p>

  <p class="para">
   Метод <a href="language.oop5.overloading.php#object.get" class="link">__get()</a> будет выполнен при чтении
   данных из недоступных (защищённых или приватных) или несуществующих свойств.
  </p>

  <p class="para">
   Метод <a href="language.oop5.overloading.php#object.isset" class="link">__isset()</a> будет выполнен при
   использовании <span class="function"><a href="function.isset.php" class="function">isset()</a></span> или <span class="function"><a href="function.empty.php" class="function">empty()</a></span>
   на недоступных (защищённых или приватных) или несуществующих свойствах.
  </p>

  <p class="para">
   Метод <a href="language.oop5.overloading.php#object.unset" class="link">__unset()</a> будет выполнен при вызове
   <span class="function"><a href="function.unset.php" class="function">unset()</a></span> на недоступном (защищённом или приватном) или несуществующем свойстве.
  </p>

  <p class="para">
   Аргумент <var class="varname">$name</var> представляет собой имя
   вызываемого свойства. Метод <a href="language.oop5.overloading.php#object.set" class="link">__set()</a>
   содержит аргумент <var class="varname">$value</var>, представляющий
   собой значение, которое будет записано в свойство с именем
   <var class="varname">$name</var>.
  </p>

  <p class="para">
   Перегрузка свойств работает только в контексте объекта.
   Данные магические методы не будут вызваны в статическом контексте.
   Поэтому эти методы не должны объявляться
   <a href="language.oop5.static.php" class="link">статическими</a>.
   При объявлении любого магического метода как
   <code class="literal">static</code> будет выдано предупреждение.
  </p>

  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    Возвращаемое значение <a href="language.oop5.overloading.php#object.set" class="link">__set()</a> будет
    проигнорировано из-за способа обработки в PHP оператора присваивания.
    Аналогично, <a href="language.oop5.overloading.php#object.get" class="link">__get()</a> никогда не вызывается при
    объединении присваиваний, например, подобным образом:
<code class="literal"><div class="annotation-interactive cdata"><pre> $a = $obj-&gt;b = 8;</pre></div></code>
   </p>
  </p></blockquote>

  <blockquote class="note"><p><strong class="note">Замечание</strong>: 
   <p class="para">
    PHP не будет вызывать перегруженный метод изнутри того же перегруженного метода.
    Это означает, что, например, написание <code class="code">return $this-&gt;foo</code> внутри
    <a href="language.oop5.overloading.php#object.get" class="link">__get()</a> вернёт <code class="literal">null</code>
    и вызовет ошибку уровня <strong><code><a href="errorfunc.constants.php#constant.e-warning">E_WARNING</a></code></strong>, если не определено свойство <code class="literal">foo</code>,
    вместо того, чтобы вызвать метод <a href="language.oop5.overloading.php#object.get" class="link">__get()</a> во второй раз.
    Однако методы перегрузки могут неявно вызывать другие методы перегрузки (например,
    метод <a href="language.oop5.overloading.php#object.set" class="link">__set()</a> вызывает метод <a href="language.oop5.overloading.php#object.get" class="link">__get()</a>).
   </p>
  </p></blockquote>

  <div class="example" id="example-1">
   <p><strong>Пример #1 
    Перегрузка свойств с помощью методов <a href="language.oop5.overloading.php#object.get" class="link">__get()</a>,
    <a href="language.oop5.overloading.php#object.set" class="link">__set()</a>, <a href="language.oop5.overloading.php#object.isset" class="link">__isset()</a>
    и <a href="language.oop5.overloading.php#object.unset" class="link">__unset()</a>
   </strong></p>
   <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">PropertyTest<br /></span><span style="color: #007700">{<br />    </span><span style="color: #FF8000">/**  Место хранения перегружаемых данных.  */<br />    </span><span style="color: #007700">private </span><span style="color: #0000BB">$data </span><span style="color: #007700">= array();<br /><br />    </span><span style="color: #FF8000">/**  Перегрузка не применяется к объявленным свойствам.  */<br />    </span><span style="color: #007700">public </span><span style="color: #0000BB">$declared </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br /><br />    </span><span style="color: #FF8000">/**  Здесь перегрузка будет использована только при доступе вне класса.  */<br />    </span><span style="color: #007700">private </span><span style="color: #0000BB">$hidden </span><span style="color: #007700">= </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /><br />    public function </span><span style="color: #0000BB">__set</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">, </span><span style="color: #0000BB">$value</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">"Установка '</span><span style="color: #0000BB">$name</span><span style="color: #DD0000">' в '</span><span style="color: #0000BB">$value</span><span style="color: #DD0000">'\n"</span><span style="color: #007700">;<br />        </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">data</span><span style="color: #007700">[</span><span style="color: #0000BB">$name</span><span style="color: #007700">] = </span><span style="color: #0000BB">$value</span><span style="color: #007700">;<br />    }<br /><br />    public function </span><span style="color: #0000BB">__get</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">"Получение '</span><span style="color: #0000BB">$name</span><span style="color: #DD0000">'\n"</span><span style="color: #007700">;<br />        if (</span><span style="color: #0000BB">array_key_exists</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">, </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">data</span><span style="color: #007700">)) {<br />            return </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">data</span><span style="color: #007700">[</span><span style="color: #0000BB">$name</span><span style="color: #007700">];<br />        }<br /><br />        </span><span style="color: #0000BB">$trace </span><span style="color: #007700">= </span><span style="color: #0000BB">debug_backtrace</span><span style="color: #007700">();<br />        </span><span style="color: #0000BB">trigger_error</span><span style="color: #007700">(<br />            </span><span style="color: #DD0000">'Неопределённое свойство в __get(): ' </span><span style="color: #007700">. </span><span style="color: #0000BB">$name </span><span style="color: #007700">.<br />            </span><span style="color: #DD0000">' в файле ' </span><span style="color: #007700">. </span><span style="color: #0000BB">$trace</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'file'</span><span style="color: #007700">] .<br />            </span><span style="color: #DD0000">' на строке ' </span><span style="color: #007700">. </span><span style="color: #0000BB">$trace</span><span style="color: #007700">[</span><span style="color: #0000BB">0</span><span style="color: #007700">][</span><span style="color: #DD0000">'line'</span><span style="color: #007700">],<br />            </span><span style="color: #0000BB">E_USER_NOTICE</span><span style="color: #007700">);<br />        return </span><span style="color: #0000BB">null</span><span style="color: #007700">;<br />    }<br /><br />    public function </span><span style="color: #0000BB">__isset</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">"Установлено ли '</span><span style="color: #0000BB">$name</span><span style="color: #DD0000">'?\n"</span><span style="color: #007700">;<br />        return isset(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">data</span><span style="color: #007700">[</span><span style="color: #0000BB">$name</span><span style="color: #007700">]);<br />    }<br /><br />    public function </span><span style="color: #0000BB">__unset</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #DD0000">"Уничтожение '</span><span style="color: #0000BB">$name</span><span style="color: #DD0000">'\n"</span><span style="color: #007700">;<br />        unset(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">data</span><span style="color: #007700">[</span><span style="color: #0000BB">$name</span><span style="color: #007700">]);<br />    }<br /><br />    </span><span style="color: #FF8000">/**  Не магический метод, просто для примера. */<br />    </span><span style="color: #007700">public function </span><span style="color: #0000BB">getHidden</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">hidden</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">PropertyTest</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">a </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />echo </span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">a </span><span style="color: #007700">. </span><span style="color: #DD0000">"\n\n"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(isset(</span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">a</span><span style="color: #007700">));<br />unset(</span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">a</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(isset(</span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">a</span><span style="color: #007700">));<br />echo </span><span style="color: #DD0000">"\n"</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">declared </span><span style="color: #007700">. </span><span style="color: #DD0000">"\n\n"</span><span style="color: #007700">;<br /><br />echo </span><span style="color: #DD0000">"Давайте поэкспериментируем с закрытым свойством 'hidden':\n"</span><span style="color: #007700">;<br />echo </span><span style="color: #DD0000">"Закрытые свойства видны внутри класса, поэтому __get() не используется...\n"</span><span style="color: #007700">;<br />echo </span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getHidden</span><span style="color: #007700">() . </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />echo </span><span style="color: #DD0000">"Закрытые свойства не видны вне класса, поэтому __get() используется...\n"</span><span style="color: #007700">;<br />echo </span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">hidden </span><span style="color: #007700">. </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<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>
Установка &#039;a&#039; в &#039;1&#039;
Получение &#039;a&#039;
1

Установлено ли &#039;a&#039;?
bool(true)
Уничтожение &#039;a&#039;
Установлено ли &#039;a&#039;?
bool(false)

1

Давайте поэкспериментируем с закрытым свойством &#039;hidden&#039;:
Закрытые свойства видны внутри класса, поэтому __get() не используется...
2
Закрытые свойства не видны вне класса, поэтому __get() используется...
Получение &#039;hidden&#039;


Notice: Неопределённое свойство в __get(): hidden в &lt;file&gt; on line 70 in &lt;file&gt; on line 29
</pre></div>
    </div>

   </div>
  </div>

  <div class="sect2" id="language.oop5.overloading.methods">
   <h3 class="title">Перегрузка методов</h3>

   <div class="methodsynopsis dc-description" id="object.call">
    <span class="modifier">public</span> <span class="methodname"><strong>__call</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.string.php" class="type string">string</a></span> <code class="parameter">$name</code></span>, <span class="methodparam"><span class="type"><a href="language.types.array.php" class="type array">array</a></span> <code class="parameter">$arguments</code></span>): <span class="type"><a href="language.types.mixed.php" class="type mixed">mixed</a></span></div>

   <div class="methodsynopsis dc-description" id="object.callstatic"><span class="modifier">public static</span> <span class="methodname"><strong>__callStatic</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.string.php" class="type string">string</a></span> <code class="parameter">$name</code></span>, <span class="methodparam"><span class="type"><a href="language.types.array.php" class="type array">array</a></span> <code class="parameter">$arguments</code></span>): <span class="type"><a href="language.types.mixed.php" class="type mixed">mixed</a></span></div>


   <p class="para">
    <a href="language.oop5.overloading.php#object.call" class="link">__call()</a> запускается при вызове
    недоступных методов в контексте объект.
   </p>

   <p class="para">
    <a href="language.oop5.overloading.php#object.callstatic" class="link">__callStatic()</a> запускается
    при вызове недоступных методов в статическом контексте.
   </p>

   <p class="para">
    Аргумент <var class="varname">$name</var> представляет собой имя
    вызываемого метода. Аргумент <var class="varname">$arguments</var>
    представляет собой нумерованный массив, содержащий параметры,
    переданные в вызываемый метод <var class="varname">$name</var>.
   </p>

   <div class="example" id="example-2">
    <p><strong>Пример #2 
     Перегрузка методов с помощью методов <a href="language.oop5.overloading.php#object.call" class="link">__call()</a>
     и <a href="language.oop5.overloading.php#object.callstatic" class="link">__callStatic()</a>
    </strong></p>
    <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">MethodTest </span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">__call</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">, </span><span style="color: #0000BB">$arguments</span><span style="color: #007700">) {<br />        </span><span style="color: #FF8000">// Замечание: значение $name регистрозависимо.<br />        </span><span style="color: #007700">echo </span><span style="color: #DD0000">"Вызов метода '</span><span style="color: #0000BB">$name</span><span style="color: #DD0000">' "<br />             </span><span style="color: #007700">. </span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #DD0000">', '</span><span style="color: #007700">, </span><span style="color: #0000BB">$arguments</span><span style="color: #007700">). </span><span style="color: #DD0000">"\n"</span><span style="color: #007700">;<br />    }<br /><br />    public static function </span><span style="color: #0000BB">__callStatic</span><span style="color: #007700">(</span><span style="color: #0000BB">$name</span><span style="color: #007700">, </span><span style="color: #0000BB">$arguments</span><span style="color: #007700">) {<br />        </span><span style="color: #FF8000">// Замечание: значение $name регистрозависимо.<br />        </span><span style="color: #007700">echo </span><span style="color: #DD0000">"Вызов статического метода '</span><span style="color: #0000BB">$name</span><span style="color: #DD0000">' "<br />             </span><span style="color: #007700">. </span><span style="color: #0000BB">implode</span><span style="color: #007700">(</span><span style="color: #DD0000">', '</span><span style="color: #007700">, </span><span style="color: #0000BB">$arguments</span><span style="color: #007700">). </span><span style="color: #DD0000">"\n"</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">MethodTest</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">$obj</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">runTest</span><span style="color: #007700">(</span><span style="color: #DD0000">'в контексте объекта'</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">MethodTest</span><span style="color: #007700">::</span><span style="color: #0000BB">runTest</span><span style="color: #007700">(</span><span style="color: #DD0000">'в статическом контексте'</span><span style="color: #007700">);<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>
Вызов метода &#039;runTest&#039; в контексте объекта
Вызов статического метода &#039;runTest&#039; в статическом контексте
</pre></div>
    </div>
   </div>

  </div>

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