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

contributors($setup);

?>
<div id="language.oop5.lazy-objects" class="sect1">
 <h2 class="title">Ленивые объекты</h2>

 <p class="simpara">
  Ленивый объект — объект, инициализация которого откладывается до момента отслеживания или изменения состояния.
  Отдельные примеры работы с ленивыми объектами включают:
  а) компоненты внедрения зависимостей, которые предоставляют отложенные службы, которые инициализируются на 100 %
  только когда требуются б) <abbr>ORM</abbr>-инструменты, которые предоставляют ленивые объекты,
  которые гидрируются значениями из базы данных только при обращении к ORM-объекту или в) JSON-парсер, который
  откладывает разбор до тех пор, пока к элементам не обратятся.
 </p>

 <p class="simpara">
  Поддерживаются две стратегии ленивых объектов: объекты-призраки (англ. Ghost Objects)
  и виртуальные прокси (англ. Virtual Proxies), которые здесь и дальше называются
  «ленивые призраки» и «ленивые прокси».
  В обеих стратегиях ленивый объект прикрепляется к инициализатору или фабрике,
  которая вызывается автоматически, когда состояние объекта начинают отслеживать
  или изменяют в первый раз. С точки зрения абстракции ленивые объекты-призраки
  неотличимы от неленивых: с такими объектами работают, не зная, что они ленивые,
  что разрешает коду передавать и обрабатывать такие объекты без знания о лени объектов.
  Ленивые прокси тоже прозрачны, но когда потребуется отличить ленивый объекты-прокси от реального
  экземпляра, соблюдают осторожность, поскольку у объекта-прокси и его реального экземпляра
  разные идентификаторы.
 </p>

 <blockquote class="note"><p><strong class="note">Замечание</strong>: 
  <strong>Сведения о версии</strong><br />
  <span class="simpara">
   Ленивые объекты появились в PHP 8.4.
  </span>
 </p></blockquote>

 <div class="sect2" id="language.oop5.lazy-objects.creation">
  <h3 class="title">Создание ленивых объектов</h3>

  <p class="simpara">
   PHP разрешает создавать ленивыми экземпляры пользовательских классов
   или стандартного PHP-класса <span class="classname"><a href="class.stdclass.php" class="classname">stdClass</a></span> (другие внутренние классы
   не поддерживаются) или сбрасывать экземпляры этих классов, чтобы сделать объект ленивым.
   Точки входа, через которые создают ленивые объекты, —
   методы <span class="methodname"><a href="reflectionclass.newlazyghost.php" class="methodname">ReflectionClass::newLazyGhost()</a></span>
   и <span class="methodname"><a href="reflectionclass.newlazyproxy.php" class="methodname">ReflectionClass::newLazyProxy()</a></span>.
  </p>

  <p class="simpara">
   Оба метода принимают callback-функцию, которая вызывается, когда требуется инициализация объекта.
   Поведение, которого ждут от функции обратного вызова, меняется, и зависит от стратегии. Стратегии описывает
   справочная документация к методам.
  </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">Example<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(public </span><span style="color: #0000BB">int $prop</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #0000BB">__METHOD__</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">$reflector </span><span style="color: #007700">= new </span><span style="color: #0000BB">ReflectionClass</span><span style="color: #007700">(</span><span style="color: #0000BB">Example</span><span style="color: #007700">::class);<br /></span><span style="color: #0000BB">$lazyObject </span><span style="color: #007700">= </span><span style="color: #0000BB">$reflector</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">newLazyGhost</span><span style="color: #007700">(function (</span><span style="color: #0000BB">Example $object</span><span style="color: #007700">) {<br />    </span><span style="color: #FF8000">// Инициализируем объект позже, на месте — по требованию<br />    </span><span style="color: #0000BB">$object</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">__construct</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">);<br />});<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$lazyObject</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">$lazyObject</span><span style="color: #007700">));<br /><br /></span><span style="color: #FF8000">// Запускаем инициализацию<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$lazyObject</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prop</span><span style="color: #007700">);</span></span></code></div>
   </div>

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

   <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
lazy ghost object(Example)#3 (0) {
[&quot;prop&quot;]=&gt;
uninitialized(int)
}
string(7) &quot;Example&quot;
Example::__construct
int(1)
</pre></div>
   </div>
  </div>

  <div class="example" id="example-2">
   <p><strong>Пример #2 Пример создания ленивого прокси</strong></p>
   <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">Example<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(public </span><span style="color: #0000BB">int $prop</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #0000BB">__METHOD__</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">$reflector </span><span style="color: #007700">= new </span><span style="color: #0000BB">ReflectionClass</span><span style="color: #007700">(</span><span style="color: #0000BB">Example</span><span style="color: #007700">::class);<br /></span><span style="color: #0000BB">$lazyObject </span><span style="color: #007700">= </span><span style="color: #0000BB">$reflector</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">newLazyProxy</span><span style="color: #007700">(function (</span><span style="color: #0000BB">Example $object</span><span style="color: #007700">) {<br />    </span><span style="color: #FF8000">// Создаём и возвращаем реальный экземпляр<br />    </span><span style="color: #007700">return new </span><span style="color: #0000BB">Example</span><span style="color: #007700">(</span><span style="color: #0000BB">1</span><span style="color: #007700">);<br />});<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$lazyObject</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">$lazyObject</span><span style="color: #007700">));<br /><br /></span><span style="color: #FF8000">// Запускаем инициализацию<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$lazyObject</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prop</span><span style="color: #007700">);</span></span></code></div>
   </div>

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

   <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
lazy proxy object(Example)#3 (0) {
  [&quot;prop&quot;]=&gt;
  uninitialized(int)
}
string(7) &quot;Example&quot;
Example::__construct
int(1)
</pre></div>
   </div>
  </div>

  <p class="simpara">
   Доступ к свойствам ленивого объекта запускает инициализацию ленивого объекта,
   включая доступ через класс <span class="classname"><a href="class.reflectionproperty.php" class="classname">ReflectionProperty</a></span>.
   При этом отдельные свойства иногда известны заранее и требуется предотвратить срабатывание
   инициализации при доступе:
  </p>

  <div class="example" id="example-3">
   <p><strong>Пример #3 Пример упреждающей инициализации свойств</strong></p>
   <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">BlogPost<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(<br />        public </span><span style="color: #0000BB">int $id</span><span style="color: #007700">,<br />        public </span><span style="color: #0000BB">string $title</span><span style="color: #007700">,<br />        public </span><span style="color: #0000BB">string $content</span><span style="color: #007700">,<br />    ) {}<br />}<br /><br /></span><span style="color: #0000BB">$reflector </span><span style="color: #007700">= new </span><span style="color: #0000BB">ReflectionClass</span><span style="color: #007700">(</span><span style="color: #0000BB">BlogPost</span><span style="color: #007700">::class);<br /><br /></span><span style="color: #0000BB">$post </span><span style="color: #007700">= </span><span style="color: #0000BB">$reflector</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">newLazyGhost</span><span style="color: #007700">(function (</span><span style="color: #0000BB">$post</span><span style="color: #007700">) {<br />    </span><span style="color: #0000BB">$data </span><span style="color: #007700">= </span><span style="color: #0000BB">fetch_from_store</span><span style="color: #007700">(</span><span style="color: #0000BB">$post</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">id</span><span style="color: #007700">);<br />    </span><span style="color: #0000BB">$post</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">__construct</span><span style="color: #007700">(</span><span style="color: #0000BB">$data</span><span style="color: #007700">[</span><span style="color: #DD0000">'id'</span><span style="color: #007700">], </span><span style="color: #0000BB">$data</span><span style="color: #007700">[</span><span style="color: #DD0000">'title'</span><span style="color: #007700">], </span><span style="color: #0000BB">$data</span><span style="color: #007700">[</span><span style="color: #DD0000">'content'</span><span style="color: #007700">]);<br />});<br /><br /></span><span style="color: #FF8000">// Без этой строки вызов метода ReflectionProperty::setValue(), который идёт следующим,<br />// запустит инициализацию<br /></span><span style="color: #0000BB">$reflector</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getProperty</span><span style="color: #007700">(</span><span style="color: #DD0000">'id'</span><span style="color: #007700">)-&gt;</span><span style="color: #0000BB">skipLazyInitialization</span><span style="color: #007700">(</span><span style="color: #0000BB">$post</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">$reflector</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getProperty</span><span style="color: #007700">(</span><span style="color: #DD0000">'id'</span><span style="color: #007700">)-&gt;</span><span style="color: #0000BB">setValue</span><span style="color: #007700">(</span><span style="color: #0000BB">$post</span><span style="color: #007700">, </span><span style="color: #0000BB">123</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// Альтернативный способ установки значения свойства без запуска ленивой инициализации<br /></span><span style="color: #0000BB">$reflector</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">getProperty</span><span style="color: #007700">(</span><span style="color: #DD0000">'id'</span><span style="color: #007700">)-&gt;</span><span style="color: #0000BB">setRawValueWithoutLazyInitialization</span><span style="color: #007700">(</span><span style="color: #0000BB">$post</span><span style="color: #007700">, </span><span style="color: #0000BB">123</span><span style="color: #007700">);<br /><br /></span><span style="color: #FF8000">// Доступ к свойству id возможен без запуска инициализации.<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(</span><span style="color: #0000BB">$post</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">id</span><span style="color: #007700">);</span></span></code></div>
   </div>

  </div>

  <p class="simpara">
   Методы <span class="methodname"><a href="reflectionproperty.skiplazyinitialization.php" class="methodname">ReflectionProperty::skipLazyInitialization()</a></span>
   и <span class="methodname"><a href="reflectionproperty.setrawvaluewithoutlazyinitialization.php" class="methodname">ReflectionProperty::setRawValueWithoutLazyInitialization()</a></span>
   предлагают способы обхода инициализации ленивых объектов при доступе к свойству.
  </p>
 </div>

 <div class="sect2" id="language.oop5.lazy-objects.patterns">
  <h3 class="title">О стратегиях ленивых объектов</h3>

  <p class="simpara">
   <em>Ленивые призраки</em> — объекты, которые инициализируются на месте,
   и после инициализации неотличимы от объекта, который никогда не был ленивым.
   Стратегию применяют, когда контролируют как создание экземпляра, так и инициализацию объекта,
   что делает стратегию непригодной, если хотя бы один из этих процессов управляется другой стороной.
  </p>

  <p class="simpara">
   <em>Ленивые прокси</em> после инициализации действуют как прокси
   до реального экземпляра: операции на инициализированном ленивом прокси перенаправляются
   на реальный экземпляр. Создание реального экземпляра разрешается делегировать другой стороне,
   что делает эту стратегию полезной, когда ленивые призраки не подходят.
   Хотя ленивые прокси почти так же прозрачны, как ленивые призраки, потребуется осторожность,
   когда потребуется отличить ленивый прокси от реального объекта, поскольку объект-прокси
   и его реальный экземпляр получают разные идентификаторы.
  </p>
 </div>

 <div class="sect2" id="language.oop5.lazy-objects.lifecycle">
  <h3 class="title">Жизненный цикл ленивых объектов</h3>

  <p class="simpara">
   Объекты делают ленивыми либо сразу — путём вызова метода
   <span class="methodname"><a href="reflectionclass.newlazyghost.php" class="methodname">ReflectionClass::newLazyGhost()</a></span>
   или <span class="methodname"><a href="reflectionclass.newlazyproxy.php" class="methodname">ReflectionClass::newLazyProxy()</a></span>,
   либо создают, а затем передают реальный объект в метод
   <span class="methodname"><a href="reflectionclass.resetaslazyghost.php" class="methodname">ReflectionClass::resetAsLazyGhost()</a></span>
   или <span class="methodname"><a href="reflectionclass.resetaslazyproxy.php" class="methodname">ReflectionClass::resetAsLazyProxy()</a></span>. Следующие операции
   инициализируют ленивый объект:
  </p>

  <ul class="simplelist">
   <li>
    Взаимодействие с объектом, при котором вызывается автоматическая инициализация.
    См. «<a href="language.oop5.lazy-objects.php#language.oop5.lazy-objects.initialization-triggers" class="link">Триггеры инициализации</a>».
   </li>
   <li>
    Пометка каждого свойства ленивого объекта как неленивое методом
    <span class="methodname"><a href="reflectionproperty.skiplazyinitialization.php" class="methodname">ReflectionProperty::skipLazyInitialization()</a></span>
    или <span class="methodname"><a href="reflectionproperty.setrawvaluewithoutlazyinitialization.php" class="methodname">ReflectionProperty::setRawValueWithoutLazyInitialization()</a></span>.
   </li>
   <li>
    Явный вызов метода <span class="methodname"><a href="reflectionclass.initializelazyobject.php" class="methodname">ReflectionClass::initializeLazyObject()</a></span>
    или <span class="methodname"><a href="reflectionclass.marklazyobjectasinitialized.php" class="methodname">ReflectionClass::markLazyObjectAsInitialized()</a></span>.
   </li>
  </ul>

  <p class="simpara">
   Поскольку ленивые объекты становятся инициализированными,
   когда каждое свойство ленивого объекта пометили неленивым, приведённые методы не пометят
   объект как ленивый, если ни одно свойство нельзя пометить ленивым.
  </p>
 </div>

 <div class="sect2" id="language.oop5.lazy-objects.initialization-triggers">
  <h3 class="title">Триггеры инициализации</h3>

  <p class="simpara">
   Ленивые объекты спроектировали на 100 % прозрачными для потребителей,
   поэтому обычные операции, которые отслеживают или изменяют состояние объекта,
   автоматически инициализируют ленивый объект перед выполнением операции.
   Инициализацию запускает следующий неполный список операций:
  </p>

  <ul class="simplelist">
   <li>
    Чтение или запись свойства.
   </li>
   <li>
    Проверка установки свойства или удаление свойства.
   </li>
   <li>
    Доступ к свойству или изменение свойства методами
    <span class="methodname"><a href="reflectionproperty.getvalue.php" class="methodname">ReflectionProperty::getValue()</a></span>,
    <span class="methodname"><a href="reflectionproperty.getrawvalue.php" class="methodname">ReflectionProperty::getRawValue()</a></span>,
    <span class="methodname"><a href="reflectionproperty.setvalue.php" class="methodname">ReflectionProperty::setValue()</a></span>
    или <span class="methodname"><a href="reflectionproperty.setrawvalue.php" class="methodname">ReflectionProperty::setRawValue()</a></span>.
   </li>
   <li>
    Получение списка свойств методами
    <span class="methodname"><strong>ReflectionObject::getProperties()</strong></span>
    или <span class="methodname"><strong>ReflectionObject::getProperty()</strong></span>,
    или функцией <span class="function"><a href="function.get-object-vars.php" class="function">get_object_vars()</a></span>.
   </li>
   <li>
    Итерация по свойствам объекта, который не реализует интерфейс
    <span class="interfacename"><a href="class.iterator.php" class="interfacename">Iterator</a></span>
    или <span class="interfacename"><a href="class.iteratoraggregate.php" class="interfacename">IteratorAggregate</a></span>,
    конструкцией <a href="control-structures.foreach.php" class="link">foreach</a>.
   </li>
   <li>
    Сериализация ленивого объекта функциями <span class="function"><a href="function.serialize.php" class="function">serialize()</a></span>,
    <span class="function"><a href="function.json-encode.php" class="function">json_encode()</a></span> или другими.
   </li>
   <li>
    <a href="language.oop5.lazy-objects.php#language.oop5.lazy-objects.cloning" class="link">Клонирование</a>
    ленивого объекта.
   </li>
  </ul>

  <p class="simpara">
   Вызовы методов, которые не обращаются к состоянию объекта, не инициализируют ленивый объект.
   Аналогично, взаимодействия с объектом, которые вызывают магические методы или функции хука,
   не инициализируют ленивый объект, если для этих методов или функций не открыт доступ
   к состоянию объекта.
  </p>

  <div class="sect3">
   <h4 class="title">Нетриггерные операции</h4>

   <p class="simpara">
    Следующие специальные методы или низкоуровневые операции получают
    доступ к ленивым объектам или изменяют ленивые объекты без запуска инициализации:
   </p>

   <ul class="simplelist">
    <li>
     Пометка свойств неленивыми методом
     <span class="methodname"><a href="reflectionproperty.skiplazyinitialization.php" class="methodname">ReflectionProperty::skipLazyInitialization()</a></span>
     или <span class="methodname"><a href="reflectionproperty.setrawvaluewithoutlazyinitialization.php" class="methodname">ReflectionProperty::setRawValueWithoutLazyInitialization()</a></span>.
    </li>
    <li>
     Получение внутреннего представления свойств
     функцией <span class="function"><a href="function.get-mangled-object-vars.php" class="function">get_mangled_object_vars()</a></span>
     или через <a href="language.types.array.php#language.types.array.casting" class="link">приведение объекта к массиву</a>.
    </li>
    <li>
     Вызов функции <span class="function"><a href="function.serialize.php" class="function">serialize()</a></span> при установке флага
     <strong><code><a href="class.reflectionclass.php#reflectionclass.constants.skip-initialization-on-serialize">ReflectionClass::SKIP_INITIALIZATION_ON_SERIALIZE</a></code></strong>,
     если только функция
     <a href="language.oop5.magic.php#object.serialize" class="link">__serialize()</a>
     или <a href="language.oop5.magic.php#object.sleep" class="link">__sleep()</a> не запустила инициализацию.
    </li>
    <li>
     Вызов магического метода <span class="methodname"><strong>ReflectionObject::__toString()</strong></span>.
    </li>
    <li>
     Вызов функции <span class="function"><a href="function.var-dump.php" class="function">var_dump()</a></span>
     или <span class="function"><a href="function.debug-zval-dump.php" class="function">debug_zval_dump()</a></span>, если только магический метод
     <a href="language.oop5.magic.php#object.debuginfo" class="link">__debugInfo()</a> не запустил
     инициализацию.
    </li>
   </ul>
  </div>
 </div>

 <div class="sect2" id="language.oop5.lazy-objects.initialization-sequence">
  <h3 class="title">Последовательность инициализации</h3>

  <p class="simpara">
   Раздел описывает характерные для стратегий последовательности операций,
   которые выполняются при запуске инициализации.
  </p>

  <div class="sect3">
   <h4 class="title">Объекты-призраки</h4>
   <ul class="simplelist">
    <li>
     Ленивый призрак помечается как неленивый.
    </li>
    <li>
     Свойствам, которые не инициализировали методом
     <span class="methodname"><a href="reflectionproperty.skiplazyinitialization.php" class="methodname">ReflectionProperty::skipLazyInitialization()</a></span>
     или <span class="methodname"><a href="reflectionproperty.setrawvaluewithoutlazyinitialization.php" class="methodname">ReflectionProperty::setRawValueWithoutLazyInitialization()</a></span>,
     устанавливаются значения по умолчанию, если такие определили в классе. На этом этапе объект
     напоминает объект, который создали методом
     <span class="methodname"><a href="reflectionclass.newinstancewithoutconstructor.php" class="methodname">ReflectionClass::newInstanceWithoutConstructor()</a></span>,
     за исключением свойств, которые уже инициализировались.
    </li>
    <li>
     Затем вызывается callback-функция инициализатора с объектом в качестве первого аргумента.
     Ожидается, что функция обратного вызова — хотя это и не обязательно —
     инициализирует состояние объекта и вернёт <strong><code><a href="reserved.constants.php#constant.null">null</a></code></strong> или не вернёт никакого значения.
     На этом этапе объект перестаёт быть ленивым, поэтому функция получает прямой доступ
     к свойствам реального объекта.
    </li>
   </ul>
   <p class="simpara">
    После инициализации объект неотличим от объекта, который никогда не был ленивым.
   </p>
  </div>

  <div class="sect3">
   <h4 class="title">Объекты-прокси</h4>
   <ul class="simplelist">
    <li>
     Ленивый прокси помечается как неленивый.
    </li>
    <li>
     В отличие от ленивых призраков, свойства ленивых прокси на этом этапе не изменяются.
    </li>
    <li>
     Фабричная callback-функция вызывается с объектом в качестве первого аргумента
     и возвращает неленивый экземпляр совместимого класса. Смотрите описание
     метода <span class="methodname"><a href="reflectionclass.newlazyproxy.php" class="methodname">ReflectionClass::newLazyProxy()</a></span>.
    </li>
    <li>
     Экземпляр, который вернула функция обратного вызова, называется
     <em>реальным экземпляром</em> и прикрепляется к прокси.
    </li>
    <li>
     Значения свойств ленивого прокси отбрасываются так, как если бы вызвали
     языковую конструкцию <span class="function"><a href="function.unset.php" class="function">unset()</a></span>.
    </li>
   </ul>
   <p class="simpara">
    После инициализации доступ к свойствам объекта-прокси даст тот же результат,
    что и доступ к тому же свойству реального экземпляра; обращения к свойствам
    объекта-прокси перенаправляются на реальный экземпляр, включая объявленные,
    динамические, несуществующие свойства или свойства, которые пометили методом
    <span class="methodname"><a href="reflectionproperty.skiplazyinitialization.php" class="methodname">ReflectionProperty::skipLazyInitialization()</a></span>
    или <span class="methodname"><a href="reflectionproperty.setrawvaluewithoutlazyinitialization.php" class="methodname">ReflectionProperty::setRawValueWithoutLazyInitialization()</a></span>.
   </p>
   <p class="simpara">
    Сам объект-прокси не заменяется и <em>не</em> подменяет собой
    реальный экземпляр.
   </p>
   <p class="simpara">
    Хотя фабрика получает прокси как первый аргумент, ожидается, что фабричная функция
    не станет изменять объект-прокси. Изменения разрешаются, но потеряются на заключительном
    этапе инициализации. Однако прокси иногда помогает принимать решения
    на основе значений инициализированных свойств, класса, самого объекта или его идентификатора.
    Например, инициализатор создаёт реальный экземпляр на основе значения инициализированного
    свойства.
   </p>
  </div>

  <div class="sect3">
   <h4 class="title">Общее поведение</h4>

   <p class="simpara">
    Область действия и контекст переменной <var class="varname">$this</var> инициализатора или фабричной
    функции остаются неизменными, и применяются стандартные ограничения видимости.
   </p>

   <p class="simpara">
    После успешной инициализации объект больше не ссылается на инициализатор
    или фабричную функцию и доступен для освобождения, если на объект не осталось
    других ссылок.
   </p>

   <p class="simpara">
    Состояние объекта возвращается к состоянию до инициализации,
    а объект снова помечается как ленивый, если инициализатор генерирует исключение.
    Другими словами, каждое воздействие на сам объект отменяется.
    Другие побочные эффекты наподобие воздействия на другие объекты не отменяются.
    Это предотвращает предоставление частично инициализированного экземпляра
    при ошибке.
   </p>
  </div>
 </div>

 <div class="sect2" id="language.oop5.lazy-objects.cloning">
  <h3 class="title">Клонирование</h3>

  <p class="simpara">
   <a href="language.oop5.cloning.php" class="link">Клонирование</a>
   ленивого объекта запускает его инициализацию раньше, чем создаётся
   клон, поэтому объект инициализируется.
  </p>

  <p class="simpara">
   При клонировании объектов-прокси клонируется как прокси, так и его реальный экземпляр,
   и возвращается клон прокси.
   Магический метод <a href="language.oop5.cloning.php#object.clone" class="link"><code class="literal">__clone</code></a>
   вызывается на реальном экземпляре, не на прокси.
   Клонированный прокси и реальный экземпляр связываются так, как они связались
   при инициализации, поэтому доступ к клону объекта-прокси перенаправляется
   на клон реального экземпляра.
  </p>

  <p class="simpara">
   Такое поведение гарантирует, что клон и исходный объект сохраняют
   разные состояния. Изменения состояния исходного объекта или состояния его инициализатора
   после клонирования не влияют на клон. Клонирование и прокси, и его реального
   экземпляра вместо возврата только клона реального экземпляра гарантирует,
   что операция клонирования стабильно возвращает объект того же класса.
  </p>
 </div>

 <div class="sect2" id="language.oop5.lazy-objects.destructors">
  <h3 class="title">Деструкторы</h3>

  <p class="simpara">
   Для ленивых призраков деструктор вызывается, только если объект инициализировали.
   Для прокси деструктор вызывается только для реального экземпляра, если реальный экземпляр существует.
  </p>

  <p class="simpara">
   Методам <span class="methodname"><a href="reflectionclass.resetaslazyghost.php" class="methodname">ReflectionClass::resetAsLazyGhost()</a></span>
   и <span class="methodname"><a href="reflectionclass.resetaslazyproxy.php" class="methodname">ReflectionClass::resetAsLazyProxy()</a></span>
   разрешается вызывать деструктор сбрасываемого объекта.
  </p>
 </div>
</div><?php manual_footer($setup); ?>