<?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 => 'zh',
  ),
  'this' => 
  array (
    0 => 'language.oop5.anonymous.php',
    1 => '匿名类',
    2 => '匿名类',
  ),
  'up' => 
  array (
    0 => 'language.oop5.php',
    1 => '类与对象',
  ),
  'prev' => 
  array (
    0 => 'language.oop5.traits.php',
    1 => 'Trait',
  ),
  'next' => 
  array (
    0 => 'language.oop5.overloading.php',
    1 => '重载',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'zh',
    '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">
  可以传递参数到匿名类的构造器，也可以继承其他类、实现接口（implement interface），以及像其他普通的类一样使用 trait：
 </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">
  匿名类被嵌套进普通 Class 后，不能访问这个外部类（Outer class）的 private（私有）、protected（受保护）方法或者属性。
  为了访问外部类（Outer class）protected 属性或方法，匿名类可以 extend（扩展）此外部类。
  为了使用外部类（Outer class）的 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">'same class'</span><span style="color: #007700">;<br />} else {<br />    echo </span><span style="color: #DD0000">'different class'</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>
same class
</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 定义 readonly 匿名类</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">// 使用匿名类<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); ?>