<?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 => 'ja',
  ),
  'this' => 
  array (
    0 => 'language.oop5.property-hooks.php',
    1 => 'プロパティフック',
    2 => 'プロパティフック',
  ),
  'up' => 
  array (
    0 => 'language.oop5.php',
    1 => 'クラスとオブジェクト',
  ),
  'prev' => 
  array (
    0 => 'language.oop5.properties.php',
    1 => 'プロパティ',
  ),
  'next' => 
  array (
    0 => 'language.oop5.constants.php',
    1 => 'クラス定数',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    'path' => 'language/oop5/property-hooks.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.oop5.property-hooks" class="sect1">
 <h2 class="title">プロパティフック</h2>

 <p class="simpara">
  プロパティフックは、他の言語では「プロパティアクセサー」とも呼ばれる仕組みで、
  プロパティの読み書き動作へ干渉し、それを上書きする機能を提供します。
  この機能には、次の2つの目的があります:
 </p>
 <ol type="1">
  <li class="listitem">
   <span class="simpara">
    get- メソッドや set- メソッドを使わずプロパティを参照しつつ、
    将来的に追加の機能を追加する余地を残す。
    フックを使わない場合の定型の get/set メソッドのほとんどは
    不要になる。
   </span>
  </li>
  <li class="listitem">
   <span class="simpara">
    実際に値を保持することなく、
    オブジェクトを説明するプロパティを実装する。
   </span>
  </li>
 </ol>
 <p class="simpara">
  static でないプロパティには <code class="literal">get</code> と <code class="literal">set</code> の2種類のフックがあります。
  それぞれ、プロパティの読み取りと書き込みの動作を上書きします。
  フックは、型付きプロパティ、型のないプロパティ、いずれにも利用可能です。
 </p>
 <p class="simpara">
  プロパティはバックドプロパティか仮想プロパティのどちらかになります。
  バックドプロパティは実体の値を持つプロパティです。
  フックを持たないプロパティは、全てバックドプロパティになります。
  仮想プロパティは、実体の値を必要としないフックだけを持つプロパティです。
  この場合、フックは実質的にメソッドと等価であり、
  オブジェクトはこのプロパティ用のメモリを必要としません。
 </p>
 <p class="simpara">
  プロパティフックは <code class="literal">readonly</code> プロパティと同時に使えません。
  <code class="literal">get</code> や <code class="literal">set</code> の動作の変更だけでなく
  アクセス自体の制限も行いたい場合、
  <a href="language.oop5.visibility.php#language.oop5.visibility-members-aviz" class="link">非対称可視性プロパティ</a> を使ってください。
 </p>

 <blockquote class="note"><p><strong class="note">注意</strong>: 
  <strong>バージョン情報</strong><br />
  <span class="simpara">
   プロパティフックは PHP 8.4 で導入されました。
  </span>
 </p></blockquote>

 <div class="sect2">
  <h3 class="title">基本的なフック構文</h3>
  <p class="simpara">
   フックを宣言する一般的な構文は次のとおりです。
  </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 /></span><span style="color: #007700">class </span><span style="color: #0000BB">Example<br /></span><span style="color: #007700">{<br />    private </span><span style="color: #0000BB">bool $modified </span><span style="color: #007700">= </span><span style="color: #0000BB">false</span><span style="color: #007700">;<br /><br />    public </span><span style="color: #0000BB">string $foo </span><span style="color: #007700">= </span><span style="color: #DD0000">'default value' </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">get </span><span style="color: #007700">{<br />            if (</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">modified</span><span style="color: #007700">) {<br />                return </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo </span><span style="color: #007700">. </span><span style="color: #DD0000">' (modified)'</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">foo</span><span style="color: #007700">;<br />        }<br />        </span><span style="color: #0000BB">set</span><span style="color: #007700">(</span><span style="color: #0000BB">string $value</span><span style="color: #007700">) {<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo </span><span style="color: #007700">= </span><span style="color: #0000BB">strtolower</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">modified </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br />        }<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$example </span><span style="color: #007700">= new </span><span style="color: #0000BB">Example</span><span style="color: #007700">();<br /></span><span style="color: #0000BB">$example</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo </span><span style="color: #007700">= </span><span style="color: #DD0000">'changed'</span><span style="color: #007700">;<br />print </span><span style="color: #0000BB">$example</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo</span><span style="color: #007700">;<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="simpara">
   <var class="varname">$foo</var> プロパティの末尾はセミコロンではなく <code class="literal">{}</code> です。
   これがフックの存在を表します。
   ここでは <code class="literal">get</code> と <code class="literal">set</code> 両方のフックを定義していますが、
   一方だけ定義することも可能です。
   どちらのフックも <code class="literal">{}</code> の中に任意のコードを書くことができます。
  </p>
  <p class="simpara">
   <code class="literal">set</code> フックは、渡される値の型と名前を
   メソッドと同じ書式で指定できます。
   この型はプロパティの型と同じか、
   <a href="language.oop5.variance.php#language.oop5.variance.contravariance" class="link">反変</a> (より広い型) でなければなりません。
   たとえば <span class="type"><a href="language.types.string.php" class="type string">string</a></span> 型のプロパティに対しては、
   <span class="type"><span class="type"><a href="language.types.string.php" class="type string">string</a></span>|<span class="type"><a href="class.stringable.php" class="type Stringable">Stringable</a></span></span> を受け取る <code class="literal">set</code> フックを定義できますが、
   <span class="type"><a href="language.types.array.php" class="type array">array</a></span> のみを受け取るものは定義できません。
  </p>
  <p class="simpara">
   少なくとも一方のフックが <code class="code">$this-&gt;foo</code>（プロパティ自体）を参照しているため、
   このプロパティはバックドプロパティになります。
   <code class="code">$example-&gt;foo = &#039;changed&#039;</code> が呼び出されると、
   渡された文字列は小文字に変換され、それが値として保存されます。
   プロパティを読み取る際には、保存された値に対し、条件に応じて追加の文字列が
   付与されます。
  </p>
  <p class="simpara">
   よくあるケースに対応するために、いくつかの短縮構文が用意されています。
  </p>
  <p class="simpara">
   <code class="literal">get</code> フックが単独の式である場合、
   <code class="literal">{}</code> を省略してアロー式で置き換えることができます。
  </p>
  <div class="example" id="example-2">
   <p><strong>例2 プロパティの get 式</strong></p>
   <div class="example-contents"><p>
    この例は前の例と等価です。
   </p></div>
   <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">Example<br /></span><span style="color: #007700">{<br />    private </span><span style="color: #0000BB">bool $modified </span><span style="color: #007700">= </span><span style="color: #0000BB">false</span><span style="color: #007700">;<br /><br />    public </span><span style="color: #0000BB">string $foo </span><span style="color: #007700">= </span><span style="color: #DD0000">'default value' </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">get </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo </span><span style="color: #007700">. (</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">modified </span><span style="color: #007700">? </span><span style="color: #DD0000">' (modified)' </span><span style="color: #007700">: </span><span style="color: #DD0000">''</span><span style="color: #007700">);<br /><br />        </span><span style="color: #0000BB">set</span><span style="color: #007700">(</span><span style="color: #0000BB">string $value</span><span style="color: #007700">) {<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo </span><span style="color: #007700">= </span><span style="color: #0000BB">strtolower</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">modified </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br />        }<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="simpara">
   <code class="literal">set</code> フックのパラメータの型がプロパティの型と同じ場合 (典型的にはそうなります)、
   その型は省略可能です。この場合、渡される値には自動的に <var class="varname">$value</var> という名前が付きます。
  </p>
  <div class="example" id="example-3">
   <p><strong>例3 プロパティ set のデフォルト</strong></p>
   <div class="example-contents"><p>
    この例は前の例と等価です。
   </p></div>
   <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">Example<br /></span><span style="color: #007700">{<br />    private </span><span style="color: #0000BB">bool $modified </span><span style="color: #007700">= </span><span style="color: #0000BB">false</span><span style="color: #007700">;<br /><br />    public </span><span style="color: #0000BB">string $foo </span><span style="color: #007700">= </span><span style="color: #DD0000">'default value' </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">get </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo </span><span style="color: #007700">. (</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">modified </span><span style="color: #007700">? </span><span style="color: #DD0000">' (modified)' </span><span style="color: #007700">: </span><span style="color: #DD0000">''</span><span style="color: #007700">);<br /><br />        </span><span style="color: #0000BB">set </span><span style="color: #007700">{<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo </span><span style="color: #007700">= </span><span style="color: #0000BB">strtolower</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">modified </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br />        }<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="simpara">
   <code class="literal">set</code> フックが、渡された値を変形して保存するだけの場合には、
   アロー式でより簡略にできます。
   式の評価結果が値として保存されます。
  </p>
  <div class="example" id="example-4">
   <p><strong>例4 プロパティの set 式</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">Example<br /></span><span style="color: #007700">{<br />    private </span><span style="color: #0000BB">bool $modified </span><span style="color: #007700">= </span><span style="color: #0000BB">false</span><span style="color: #007700">;<br /><br />    public </span><span style="color: #0000BB">string $foo </span><span style="color: #007700">= </span><span style="color: #DD0000">'default value' </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">get </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">foo </span><span style="color: #007700">. (</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">modified </span><span style="color: #007700">? </span><span style="color: #DD0000">' (modified)' </span><span style="color: #007700">: </span><span style="color: #DD0000">''</span><span style="color: #007700">);<br />        </span><span style="color: #0000BB">set </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">strtolower</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="simpara">
   この例は <code class="code">$this-&gt;modified</code> の値を更新していないため
   前の例と等価ではありません。
   set フック内で複数の文が必要な場合、中括弧付きの構文を使用してください。
  </p>
  <p class="simpara">
   プロパティは状況に応じて、一方または双方のフックを実装するか、どちらも実装しないことができます。
   それぞれの短縮構文は独立しており、
   たとえば「短縮構文の get と 通常の set」
   「型を明示した短縮構文の set」など、いずれも有効です。
  </p>
  <p class="simpara">
   バックドプロパティで <code class="literal">get</code> や <code class="literal">set</code> のフックを省略した場合、
   それはデフォルトの読み書き動作になります。
  </p>
  <blockquote class="note"><p><strong class="note">注意</strong>: 
   <span class="simpara">
    フックは
    <a href="language.oop5.decon.php#language.oop5.decon.constructor.promotion" class="link">コンストラクタのプロモーション</a>
    にも定義できます。ただし、コンストラクタで受け取る値は
    <code class="literal">set</code> フックが受け入れる型ではなく、
    プロパティの本来の型に一致しなければならない点に注意してください。
   </span>
   <span class="simpara">
    次のような例を考えます:
   </span>
   <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">Example<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(<br />        public private(</span><span style="color: #0000BB">set</span><span style="color: #007700">) </span><span style="color: #0000BB">DateTimeInterface $created </span><span style="color: #007700">{<br />            </span><span style="color: #0000BB">set </span><span style="color: #007700">(</span><span style="color: #0000BB">string</span><span style="color: #007700">|</span><span style="color: #0000BB">DateTimeInterface $value</span><span style="color: #007700">) {<br />                if (</span><span style="color: #0000BB">is_string</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">)) {<br />                    </span><span style="color: #0000BB">$value </span><span style="color: #007700">= new </span><span style="color: #0000BB">DateTimeImmutable</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />                }<br />                </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">created </span><span style="color: #007700">= </span><span style="color: #0000BB">$value</span><span style="color: #007700">;<br />            }<br />        },<br />    ) {<br />    }<br />}</span></span></code></div>
   </div>

   <span class="simpara">
    内部では次のような形で処理されます:
   </span>
   <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">Example<br /></span><span style="color: #007700">{<br />    public private(</span><span style="color: #0000BB">set</span><span style="color: #007700">) </span><span style="color: #0000BB">DateTimeInterface $created </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">set </span><span style="color: #007700">(</span><span style="color: #0000BB">string</span><span style="color: #007700">|</span><span style="color: #0000BB">DateTimeInterface $value</span><span style="color: #007700">) {<br />            if (</span><span style="color: #0000BB">is_string</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">)) {<br />                </span><span style="color: #0000BB">$value </span><span style="color: #007700">= new </span><span style="color: #0000BB">DateTimeImmutable</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />            }<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">created </span><span style="color: #007700">= </span><span style="color: #0000BB">$value</span><span style="color: #007700">;<br />        }<br />    }<br /><br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(<br />        </span><span style="color: #0000BB">DateTimeInterface $created</span><span style="color: #007700">,<br />    ) {<br />        </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">created </span><span style="color: #007700">= </span><span style="color: #0000BB">$created</span><span style="color: #007700">;<br />    }<br />}</span></span></code></div>
   </div>

   <span class="simpara">
    コンストラクタ以外からプロパティに値を書き込む時は <span class="type"><a href="language.types.string.php" class="type string">string</a></span> か
    <span class="interfacename"><a href="class.datetimeinterface.php" class="interfacename">DateTimeInterface</a></span> を受け入れますが、
    コンストラクタからは <span class="interfacename"><a href="class.datetimeinterface.php" class="interfacename">DateTimeInterface</a></span> のみ受け入れます。
    プロパティの型 (<span class="interfacename"><a href="class.datetimeinterface.php" class="interfacename">DateTimeInterface</a></span>) が
    コンストラクタのシグネチャのパラメータ型として使われ、
    <code class="literal">set</code> フックが受け入れる型は参照されないためです。
   </span>
   <span class="simpara">
    このような振る舞いがコンストラクタでも必要な場合、
    コンストラクタのプロモーションは使用できません。
   </span>
  </p></blockquote>
 </div>
 <div class="sect2" id="language.oop5.property-hooks.virtual">
  <h3 class="title">仮想プロパティ</h3>
  <p class="simpara">
   仮想プロパティは、値を保持しないプロパティです。
   <code class="literal">get</code>、<code class="literal">set</code> いずれのフックも
   プロパティ自体を正確に参照していない場合、それは仮想プロパティになります。
   例えば、<code class="code">$foo</code> という名前のプロパティのフックに <code class="code">$this-&gt;foo</code> というコードが含まれれば、それはバックドプロパティです。
   次のプロパティはバックドプロパティではなく、エラーが発生します:
  </p>
  <div class="example" id="example-5">
   <p><strong>例5 無効な仮想プロパティ</strong></p>
   <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">Example<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">string $foo </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">get </span><span style="color: #007700">{<br />            </span><span style="color: #0000BB">$temp </span><span style="color: #007700">= </span><span style="color: #0000BB">__PROPERTY__</span><span style="color: #007700">;<br />            return </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">$temp</span><span style="color: #007700">; </span><span style="color: #FF8000">// $this-&gt;foo を正確に参照していません<br />        </span><span style="color: #007700">}<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="simpara">
   仮想プロパティでは、フックを省略するとその操作は存在しないとみなされ、
   使おうとするとエラーが発生します。
   仮想プロパティはオブジェクト内でメモリを消費しません。
   仮想プロパティは、例えば他の2つのプロパティを組み合わせて値を作るような
   「派生」プロパティに向いています。
  </p>
  <div class="example" id="example-6">
   <p><strong>例6 仮想プロパティ</strong></p>
   <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">Rectangle<br /></span><span style="color: #007700">{<br />    </span><span style="color: #FF8000">// 仮想プロパティ<br />    </span><span style="color: #007700">public </span><span style="color: #0000BB">int $area </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">get </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">h </span><span style="color: #007700">* </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">w</span><span style="color: #007700">;<br />    }<br /><br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(public </span><span style="color: #0000BB">int $h</span><span style="color: #007700">, public </span><span style="color: #0000BB">int $w</span><span style="color: #007700">) {}<br />}<br /><br /></span><span style="color: #0000BB">$s </span><span style="color: #007700">= new </span><span style="color: #0000BB">Rectangle</span><span style="color: #007700">(</span><span style="color: #0000BB">4</span><span style="color: #007700">, </span><span style="color: #0000BB">5</span><span style="color: #007700">);<br />print </span><span style="color: #0000BB">$s</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">area</span><span style="color: #007700">; </span><span style="color: #FF8000">// 20 と表示<br /></span><span style="color: #0000BB">$s</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">area </span><span style="color: #007700">= </span><span style="color: #0000BB">30</span><span style="color: #007700">; </span><span style="color: #FF8000">// set が定義されていないためエラー<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
  <p class="simpara">
   仮想プロパティに対して <code class="literal">get</code> と <code class="literal">set</code> 両方のフックを定義することもできます。
  </p>
 </div>
 <div class="sect2">
  <h3 class="title">スコープ</h3>
  <p class="simpara">
   全てのフックは、オブジェクトスコープで動作します。
   すなわち、全ての public、private、protected な
   メソッドやプロパティに対してアクセスできます。
   フックを持つプロパティへアクセスする場合も同様です。
   フック内で別のプロパティにアクセスしても、そのフックがバイパスされることはありません。
  </p>
  <p class="simpara">
   重要なのは、フック内で必要に応じて、
   任意の複雑なメソッドを呼び出すこともできるという点です。
  </p>
  <div class="example" id="example-7">
   <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 /></span><span style="color: #007700">class </span><span style="color: #0000BB">Person </span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">string $phone </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">set </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">sanitizePhone</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />    }<br /><br />    private function </span><span style="color: #0000BB">sanitizePhone</span><span style="color: #007700">(</span><span style="color: #0000BB">string $value</span><span style="color: #007700">): </span><span style="color: #0000BB">string </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">ltrim</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">, </span><span style="color: #DD0000">'+'</span><span style="color: #007700">);<br />        </span><span style="color: #0000BB">$value </span><span style="color: #007700">= </span><span style="color: #0000BB">ltrim</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">, </span><span style="color: #DD0000">'1'</span><span style="color: #007700">);<br /><br />        if (!</span><span style="color: #0000BB">preg_match</span><span style="color: #007700">(</span><span style="color: #DD0000">'/\d\d\d\-\d\d\d\-\d\d\d\d/'</span><span style="color: #007700">, </span><span style="color: #0000BB">$value</span><span style="color: #007700">)) {<br />            throw new </span><span style="color: #0000BB">\InvalidArgumentException</span><span style="color: #007700">();<br />        }<br />        return </span><span style="color: #0000BB">$value</span><span style="color: #007700">;<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
   </div>

  </div>
 </div>
 <div class="sect2">
  <h3 class="title">リファレンス</h3>
  <p class="simpara">
   フックはプロパティの読み書きの操作へ干渉するため、
   プロパティへのリファレンスを取得したり、
   <code class="code">$this-&gt;arrayProp[&#039;key&#039;] = &#039;value&#039;;</code> のような
   間接的な変更操作を行う場合に問題が発生します。
   リファレンスによる値の変更が set フックをバイパスしてしまうからです。
  </p>
  <p class="simpara">
   プロパティからフックを経由してリファレンスを取得する必要がある場合、
   <code class="literal">get</code> フックの先頭に <code class="literal">&amp;</code>
   を付与します。
   同じプロパティで <code class="literal">get</code> と <code class="literal">&amp;get</code> を両方定義すると
   構文エラーになります。
  </p>
  <p class="simpara">
   バックドプロパティでは <code class="literal">&amp;get</code> フックと <code class="literal">set</code> フックは同時に定義できません。
   前述のとおり、リファレンスへの書き込みは <code class="literal">set</code> フックをバイパスしてしまうためです。
   仮想プロパティでは、両フックから共有される実体の値がないため、同時に定義しても問題ありません。
  </p>
  <p class="simpara">
   配列プロパティのインデックスへ書き込みを行う場合も、暗黙的にリファレンスが使われます。
   従って、フックを伴う配列のバックドプロパティの要素の書き換えができるのは、
   <code class="literal">&amp;get</code> フックだけが定義されている場合に限ります。
   仮想プロパティの場合、
   <code class="literal">get</code> や <code class="literal">&amp;get</code> から返された配列の書き換え自体は可能ですが、
   それが実際にオブジェクトに反映されるかはフックの実装次第です。
  </p>
  <p class="simpara">
   配列全体を上書きする場合は問題ありません。他のプロパティと同様に扱われます。
   配列の個々の要素を操作する場合のみ注意が必要です。
  </p>
 </div>
 <div class="sect2">
  <h3 class="title">継承</h3>
  <div class="sect3">
   <h4 class="title">final フック</h4>
   <p class="simpara">
    フックは <a href="language.oop5.final.php" class="link">final</a> としても宣言することもできます。
    その場合はオーバーライドできなくなります。
   </p>
   <div class="example" id="example-8">
    <p><strong>例8 final フックの例</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">User<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">string $username </span><span style="color: #007700">{<br />        final </span><span style="color: #0000BB">set </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">strtolower</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />    }<br />}<br /><br />class </span><span style="color: #0000BB">Manager </span><span style="color: #007700">extends </span><span style="color: #0000BB">User<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">string $username </span><span style="color: #007700">{<br />        </span><span style="color: #FF8000">// これは許可される<br />        </span><span style="color: #0000BB">get </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">strtoupper</span><span style="color: #007700">(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">username</span><span style="color: #007700">);<br /><br />        </span><span style="color: #FF8000">// parentのsetがfinalのため許可されない。<br />        </span><span style="color: #0000BB">set </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">strtoupper</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>
   <p class="simpara">
    プロパティ自体を <a href="language.oop5.final.php" class="link">final</a> と宣言することもできます。
    final で宣言されたプロパティは子クラスで再宣言できず、
    フックを変更したりアクセス権を広げることもできません。
   </p>
   <p class="simpara">
    final と宣言したプロパティに対しフックも final とするのは
    単に冗長であり無視されます。
    これは final メソッドと同じ動作です。
   </p>
   <p class="simpara">
    子クラスでは、オーバーライドしたいフックを再定義することで、
    フックを個別にオーバーライドできます。
    フックを持たないプロパティにフックを追加することもできます。
    フックがメソッドのように振る舞うという点で、一貫した動作です。
   </p>
   <div class="example" id="example-9">
    <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 /></span><span style="color: #007700">class </span><span style="color: #0000BB">Point<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">int $x</span><span style="color: #007700">;<br />    public </span><span style="color: #0000BB">int $y</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">PositivePoint </span><span style="color: #007700">extends </span><span style="color: #0000BB">Point<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">int $x </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">set </span><span style="color: #007700">{<br />            if (</span><span style="color: #0000BB">$value </span><span style="color: #007700">&lt; </span><span style="color: #0000BB">0</span><span style="color: #007700">) {<br />                throw new </span><span style="color: #0000BB">\InvalidArgumentException</span><span style="color: #007700">(</span><span style="color: #DD0000">'Too small'</span><span style="color: #007700">);<br />            }<br />            </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">x </span><span style="color: #007700">= </span><span style="color: #0000BB">$value</span><span style="color: #007700">;<br />        }<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>
   <p class="simpara">
    それぞれのフックは親の実装を個別にオーバーライドします。
    子クラスがフックを追加する場合、親クラスのプロパティで設定されたデフォルト値は削除され、再宣言が必要です。
    これはフックのないプロパティを継承する場合と同じ動作です。
   </p>
  </div>
  <div class="sect3">
   <h4 class="title">親フックへのアクセス</h4>
   <p class="simpara">
    子クラスのフックから <code class="code">parent::$prop</code> に続き目的のフックを指定することで、
    親クラスのプロパティにアクセスできます。
    例えば <code class="code">parent::$propName::get()</code> は、
    「親クラスに定義された <var class="varname">prop</var> の get 操作を実行する」
    という意味になります。同様に set 操作も実行できます。
   </p>
   <p class="simpara">
    これらの方法でアクセスしない限り、親クラスのフックは無視されます。
    これはメソッドの動作と同じです。
    この方法で親クラスの記憶領域にアクセスできます。
    親クラスのプロパティにフックが存在しない場合、
    デフォルトの get/set 動作が使われます。
    フックは、自分自身のプロパティにおける親フック以外は呼び出せません。
   </p>
   <p class="simpara">
    上記の例は以下のように書き換えることができます。このようにすると、
    将来 <code class="literal">Point</code> クラスに独自の <code class="literal">set</code>
    フックを追加しても問題になりません（前述の例では、
    親クラスに追加されたフックが子クラスで無視されてしまいます）。
   </p>
   <div class="example" id="example-10">
    <p><strong>例10 親フックへのアクセス (set)</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">Point<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">int $x</span><span style="color: #007700">;<br />    public </span><span style="color: #0000BB">int $y</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">PositivePoint </span><span style="color: #007700">extends </span><span style="color: #0000BB">Point<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">int $x </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">set </span><span style="color: #007700">{<br />            if (</span><span style="color: #0000BB">$value </span><span style="color: #007700">&lt; </span><span style="color: #0000BB">0</span><span style="color: #007700">) {<br />                throw new </span><span style="color: #0000BB">\InvalidArgumentException</span><span style="color: #007700">(</span><span style="color: #DD0000">'Too small'</span><span style="color: #007700">);<br />            }<br />            </span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">$x</span><span style="color: #007700">::</span><span style="color: #0000BB">set</span><span style="color: #007700">(</span><span style="color: #0000BB">$value</span><span style="color: #007700">);<br />        }<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>
   <p class="simpara">
    get フックだけをオーバーライドする場合、次の例のようになります:
   </p>
   <div class="example" id="example-11">
    <p><strong>例11 親フックへのアクセス (get)</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">Strings<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">string $val</span><span style="color: #007700">;<br />}<br /><br />class </span><span style="color: #0000BB">CaseFoldingStrings </span><span style="color: #007700">extends </span><span style="color: #0000BB">Strings<br /></span><span style="color: #007700">{<br />    public </span><span style="color: #0000BB">bool $uppercase </span><span style="color: #007700">= </span><span style="color: #0000BB">true</span><span style="color: #007700">;<br /><br />    public </span><span style="color: #0000BB">string $val </span><span style="color: #007700">{<br />        </span><span style="color: #0000BB">get </span><span style="color: #007700">=&gt; </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">uppercase<br />            </span><span style="color: #007700">? </span><span style="color: #0000BB">strtoupper</span><span style="color: #007700">(</span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">$val</span><span style="color: #007700">::</span><span style="color: #0000BB">get</span><span style="color: #007700">())<br />            : </span><span style="color: #0000BB">strtolower</span><span style="color: #007700">(</span><span style="color: #0000BB">parent</span><span style="color: #007700">::</span><span style="color: #0000BB">$val</span><span style="color: #007700">::</span><span style="color: #0000BB">get</span><span style="color: #007700">());<br />    }<br />}<br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
    </div>

   </div>
  </div>
 </div>
 <div class="sect2">
  <h3 class="title">シリアライズ</h3>
  <p class="simpara">
   PHP には、オブジェクトを外部で利用したり
   デバッグしたりするための、いくつかのシリアライズ手段があります。
   その際のフックの挙動は、用途によって異なります。
   あるケースでは、プロパティに保存された生の値が使われ、
   フックはバイパスされます。
   別のケースでは、通常の読み書きと同じように
   フックを通して処理されます。
  </p>
  <ul class="simplelist">
   <li><span class="function"><a href="function.var-dump.php" class="function">var_dump()</a></span>: 生の値を使用</li>
   <li><span class="function"><a href="function.serialize.php" class="function">serialize()</a></span>: 生の値を使用</li>
   <li><span class="function"><a href="function.unserialize.php" class="function">unserialize()</a></span>: 生の値を使用</li>
   <li><a href="language.oop5.magic.php#object.serialize" class="link">__serialize()</a>/<a href="language.oop5.magic.php#object.unserialize" class="link">__unserialize()</a>: カスタムロジックと get/set フック</li>
   <li>配列キャスト: 生の値を使用</li>
   <li><span class="function"><a href="function.var-export.php" class="function">var_export()</a></span>: get フックを使用</li>
   <li><span class="function"><a href="function.json-encode.php" class="function">json_encode()</a></span>: get フックを使用</li>
   <li><span class="interfacename"><a href="class.jsonserializable.php" class="interfacename">JsonSerializable</a></span>: カスタムロジックと get フック</li>
   <li><span class="function"><a href="function.get-object-vars.php" class="function">get_object_vars()</a></span>: get フックを使用</li>
   <li><span class="function"><a href="function.get-mangled-object-vars.php" class="function">get_mangled_object_vars()</a></span>: 生の値を使用</li>
  </ul>
 </div>
</div><?php manual_footer($setup); ?>