<?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.anonymous.php',
    1 => '無名クラス',
    2 => '無名クラス',
  ),
  'up' => 
  array (
    0 => 'language.oop5.php',
    1 => 'クラスとオブジェクト',
  ),
  'prev' => 
  array (
    0 => 'language.oop5.traits.php',
    1 => 'トレイト',
  ),
  'next' => 
  array (
    0 => 'language.oop5.overloading.php',
    1 => 'オーバーロード',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'ja',
    'path' => 'language/oop5/anonymous.xml',
  ),
  'history' => 
  array (
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="language.oop5.anonymous" class="sect1">
 <h2 class="title">無名クラス</h2>

 <p class="para">
  無名クラスは、その場限りの使い捨てのオブジェクトが必要になった場合に便利です。
 </p>

 <div class="informalexample">
  <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// 明示的にクラスを宣言して使う<br /></span><span style="color: #007700">class </span><span style="color: #0000BB">Logger<br /></span><span style="color: #007700">{<br />    public function </span><span style="color: #0000BB">log</span><span style="color: #007700">(</span><span style="color: #0000BB">$msg</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #0000BB">$msg</span><span style="color: #007700">;<br />    }<br />}<br /><br /></span><span style="color: #0000BB">$util</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setLogger</span><span style="color: #007700">(new </span><span style="color: #0000BB">Logger</span><span style="color: #007700">());<br /><br /></span><span style="color: #FF8000">// 無名クラスを使う<br /></span><span style="color: #0000BB">$util</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">setLogger</span><span style="color: #007700">(new class {<br />    public function </span><span style="color: #0000BB">log</span><span style="color: #007700">(</span><span style="color: #0000BB">$msg</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #0000BB">$msg</span><span style="color: #007700">;<br />    }<br />});</span></span></code></div>
  </div>

 </div>

 <p class="para">
  コンストラクタを使って引数を渡したり、他のクラスを継承したり、
  インターフェイスを実装したり、トレイトを使ったりといった、
  普通のクラスと同じようなことが可能です。
 </p>

 <div class="informalexample">
  <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">SomeClass </span><span style="color: #007700">{}<br />interface </span><span style="color: #0000BB">SomeInterface </span><span style="color: #007700">{}<br />trait </span><span style="color: #0000BB">SomeTrait </span><span style="color: #007700">{}<br /><br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(new class(</span><span style="color: #0000BB">10</span><span style="color: #007700">) extends </span><span style="color: #0000BB">SomeClass </span><span style="color: #007700">implements </span><span style="color: #0000BB">SomeInterface </span><span style="color: #007700">{<br />    private </span><span style="color: #0000BB">$num</span><span style="color: #007700">;<br /><br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(</span><span style="color: #0000BB">$num</span><span style="color: #007700">)<br />    {<br />        </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">num </span><span style="color: #007700">= </span><span style="color: #0000BB">$num</span><span style="color: #007700">;<br />    }<br /><br />    use </span><span style="color: #0000BB">SomeTrait</span><span style="color: #007700">;<br />});</span></span></code></div>
  </div>

  <p class="para">上の例の出力は以下となります。</p>
  <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
object(class@anonymous)#1 (1) {
  [&quot;Command line code0x104c5b612&quot;:&quot;class@anonymous&quot;:private]=&gt;
  int(10)
}
</pre></div>
  </div>
 </div>

 <p class="para">
  無名クラスを別のクラス内で作っても、外側のクラスの private や protected なメソッド、
  およびプロパティにはアクセスできません。
  外側のクラスの protected プロパティやメソッドにアクセスするには、
  無名クラスに外側のクラスを継承させます。
  外側のクラスの private プロパティを無名クラスで使うには、
  コンストラクタでそれを渡す必要があります。
 </p>

 <div class="informalexample">
  <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #007700">class </span><span style="color: #0000BB">Outer<br /></span><span style="color: #007700">{<br />    private </span><span style="color: #0000BB">$prop </span><span style="color: #007700">= </span><span style="color: #0000BB">1</span><span style="color: #007700">;<br />    protected </span><span style="color: #0000BB">$prop2 </span><span style="color: #007700">= </span><span style="color: #0000BB">2</span><span style="color: #007700">;<br /><br />    protected function </span><span style="color: #0000BB">func1</span><span style="color: #007700">()<br />    {<br />        return </span><span style="color: #0000BB">3</span><span style="color: #007700">;<br />    }<br /><br />    public function </span><span style="color: #0000BB">func2</span><span style="color: #007700">()<br />    {<br />        return new class(</span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prop</span><span style="color: #007700">) extends </span><span style="color: #0000BB">Outer </span><span style="color: #007700">{<br />            private </span><span style="color: #0000BB">$prop3</span><span style="color: #007700">;<br /><br />            public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(</span><span style="color: #0000BB">$prop</span><span style="color: #007700">)<br />            {<br />                </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prop3 </span><span style="color: #007700">= </span><span style="color: #0000BB">$prop</span><span style="color: #007700">;<br />            }<br /><br />            public function </span><span style="color: #0000BB">func3</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">prop2 </span><span style="color: #007700">+ </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prop3 </span><span style="color: #007700">+ </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">func1</span><span style="color: #007700">();<br />            }<br />        };<br />    }<br />}<br /><br />echo (new </span><span style="color: #0000BB">Outer</span><span style="color: #007700">)-&gt;</span><span style="color: #0000BB">func2</span><span style="color: #007700">()-&gt;</span><span style="color: #0000BB">func3</span><span style="color: #007700">();</span></span></code></div>
  </div>

  <p class="para">上の例の出力は以下となります。</p>
  <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
6
</pre></div>
  </div>
 </div>

 <p class="para">
  同じ無名クラス宣言から作ったすべてのオブジェクトは、その同じクラスのインスタンスとなります。
 </p>

 <div class="informalexample">
  <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">function </span><span style="color: #0000BB">anonymous_class</span><span style="color: #007700">()<br />{<br />    return new class {};<br />}<br /><br />if (</span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">anonymous_class</span><span style="color: #007700">()) === </span><span style="color: #0000BB">get_class</span><span style="color: #007700">(</span><span style="color: #0000BB">anonymous_class</span><span style="color: #007700">())) {<br />    echo </span><span style="color: #DD0000">'同じクラス'</span><span style="color: #007700">;<br />} else {<br />    echo </span><span style="color: #DD0000">'違うクラス'</span><span style="color: #007700">;<br />}</span></span></code></div>
 </div>

 <p class="para">上の例の出力は以下となります。</p>
 <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
同じクラス
</pre></div>
  </div>
 </div>

 <blockquote class="note"><p><strong class="note">注意</strong>: 
  <p class="para">
   無名クラスには内部的な名前が付けられていることに注意しましょう。これは次の例で確認できます。
   ただこれは細部の実装上の話なので、この名前に依存するコードを書いてはいけません。
  </p>
  <div class="informalexample">
   <div class="example-contents">
<div class="annotation-interactive phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /></span><span style="color: #007700">echo </span><span style="color: #0000BB">get_class</span><span style="color: #007700">(new class {});</span></span></code></div>
  </div>

  <p class="para">上の例の出力は、
たとえば以下のようになります。</p>
  <div class="example-contents screen">
<div class="annotation-interactive cdata"><pre>
class@anonymous/in/oNi1A0x7f8636ad2021
</pre></div>
   </div>
  </div>
 </p></blockquote>

 <div class="sect2" id="language.oop5.anonymous.readonly">
  <h3 class="title">読み取り専用の無名クラス</h3>
  <p class="simpara">
   PHP 8.3.0 以降では、
   無名クラスにも <code class="literal">readonly</code> を適用できます。
  </p>
  <div class="example" id="language.oop5.anonymous.readonly.example">
   <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: #FF8000">// Using an anonymous class<br /></span><span style="color: #0000BB">var_dump</span><span style="color: #007700">(new readonly class(</span><span style="color: #DD0000">'[DEBUG]'</span><span style="color: #007700">) {<br />    public function </span><span style="color: #0000BB">__construct</span><span style="color: #007700">(private </span><span style="color: #0000BB">string $prefix</span><span style="color: #007700">)<br />    {<br />    }<br /><br />    public function </span><span style="color: #0000BB">log</span><span style="color: #007700">(</span><span style="color: #0000BB">$msg</span><span style="color: #007700">)<br />    {<br />        echo </span><span style="color: #0000BB">$this</span><span style="color: #007700">-&gt;</span><span style="color: #0000BB">prefix </span><span style="color: #007700">. </span><span style="color: #DD0000">' ' </span><span style="color: #007700">. </span><span style="color: #0000BB">$msg</span><span style="color: #007700">;<br />    }<br />});</span></span></code></div>
   </div>

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