php类与对象
<p>自php5起,php具有了完整的对象模型。</p><p>类名可以是任何非 PHP 保留字的合法标签。一个合法类名以字母或下划线开头,后面跟着若干字母,数字或下划线</p>
<p>一个类可以包含有属于自己的常量,变量(称为“属性”)以及函数(称为“方法”)</p>
<p>当一个方法在类定义内部被调用时,有一个可用的伪变量 <var class="varname"><var class="varname">$this</var></var>。<var class="varname"><var class="varname">$this</var></var> 是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象静态调用时也可能是另一个对象</p>
<p> 静态无$this</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> foo()
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">isset</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span><span style="color: rgba(0, 0, 0, 1)">)) {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> '$this is defined ('<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 128, 128, 1)">get_class</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> ")\n"<span style="color: rgba(0, 0, 0, 1)">;
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "\$this is not defined.\n"<span style="color: rgba(0, 0, 0, 1)">;
}
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">php7+</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> B
{
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> bar()
{
A</span>::<span style="color: rgba(0, 0, 0, 1)">foo();
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A();
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->foo();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">$this is defined (A)
//但还是会运行$this is not defined. </span>
A::foo();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Deprecated: Non-static method A::foo() should not be called statically</span>
<span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> B();
</span><span style="color: rgba(128, 0, 128, 1)">$b</span>->bar();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">$this is not defined. </span>
<span style="color: rgba(0, 0, 0, 1)">
B</span>::bar();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">$this is not defined.</span></pre>
</div>
<p>创建类的实例 new关键字</p>
<p>要创建一个类的实例,必须使用 <em>new</em> 关键字。当创建新对象时该对象总是被赋值,除非该对象定义了构造函数并且在出错时抛出了一个异常。类应在被实例化之前定义(某些情况下则必须这样)</p>
<p>如果在 <em>new</em> 之后跟着的是一个包含有类名的字符串 <span class="type">string,则该类的一个实例被创建。<span style="color: rgba(204, 153, 255, 1)">如果该类属于一个命名空间,则必须使用其完整名称</span></span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SimpleClass
{
}
</span><span style="color: rgba(128, 0, 128, 1)">$instance</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SimpleClass();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 也可以这样做:</span>
<span style="color: rgba(128, 0, 128, 1)">$className</span> = 'SimpleClass'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$instance</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(128, 0, 128, 1)">$className</span>();</pre>
</div>
<p> 在类定义内部,可以用 <em>new self</em> 和 <em>new parent</em> 创建新对象。???</p>
<p>新实例赋值给其他变量,则会访问同一实例,如果想要建立新实例则用克隆</p>
<p>赋值(内存报错数据,并将变量指向这个内存地址)</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SimpleClass
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$arg</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getArg ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>->arg.'</br>'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$instance</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SimpleClass();
</span><span style="color: rgba(128, 0, 128, 1)">$instance1</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SimpleClass();
</span><span style="color: rgba(128, 0, 128, 1)">$assigned</span> = <span style="color: rgba(128, 0, 128, 1)">$instance</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$reference</span>=& <span style="color: rgba(128, 0, 128, 1)">$instance</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$instance</span>->arg = 123<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$instance</span>->getArg();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">123</span>
<span style="color: rgba(128, 0, 128, 1)">$assigned</span>->getArg();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">123</span>
<span style="color: rgba(128, 0, 128, 1)">$reference</span>->getArg();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">123</span>
<span style="color: rgba(128, 0, 128, 1)">$instance1</span>->getArg();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">
// unset($instance);</span>
<span style="color: rgba(128, 0, 128, 1)">$instance</span> = 'abc'<span style="color: rgba(0, 0, 0, 1)">;
@</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$instance</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$reference</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$assigned</span>);</pre>
</div>
<p><img src="https://img2018.cnblogs.com/blog/1435698/201907/1435698-20190715161630308-475073771.png"></p>
<p> php5.3增加了两种方法新增实例</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Test
{
</span><span style="color: rgba(0, 0, 255, 1)">var</span> <span style="color: rgba(128, 0, 128, 1)">$a</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> getNew()<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第二种方法</span>
<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> Child <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Test
{}
</span><span style="color: rgba(128, 0, 128, 1)">$obj1</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Test();
</span><span style="color: rgba(128, 0, 128, 1)">$obj2</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(128, 0, 128, 1)">$obj1</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第一种方法</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 128, 128, 1)">get_class</span>(<span style="color: rgba(128, 0, 128, 1)">$obj2</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">test</span>
<span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$obj1</span> !== <span style="color: rgba(128, 0, 128, 1)">$obj2</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true</span>
<span style="color: rgba(128, 0, 128, 1)">$obj3</span> = Test::<span style="color: rgba(0, 0, 0, 1)">getNew();
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$obj3</span> instanceof Test);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 128, 128, 1)">get_class</span>(<span style="color: rgba(128, 0, 128, 1)">$obj3</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">test</span>
<span style="color: rgba(128, 0, 128, 1)">$obj4</span> = Child::<span style="color: rgba(0, 0, 0, 1)">getNew();
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$obj4</span> instanceof Child); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true</span>
<span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$obj4</span> instanceof Test);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">true</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 128, 128, 1)">get_class</span>(<span style="color: rgba(128, 0, 128, 1)">$obj4</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">child</span></pre>
</div>
<p>PHP 5.4.0 起,可以通过一个表达式来访问新创建对象的成员</p>
<p>echo (new DateTime())->format('Y');</p>
<p>类的属性和方法依赖于命名空间,故存在同名的情况</p>
<p>存在同名情况时,为避免匿名函数调用冲突,请用下面的方式调用匿名函数</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Foo
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$bar</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct()
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->bar = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> 42<span style="color: rgba(0, 0, 0, 1)">;
};
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> bar ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> 45<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Foo();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> as of PHP 5.3.0:</span>
<span style="color: rgba(128, 0, 128, 1)">$func</span> = <span style="color: rgba(128, 0, 128, 1)">$obj</span>-><span style="color: rgba(0, 0, 0, 1)">bar;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$func</span>(), <span style="color: rgba(255, 0, 255, 1)">PHP_EOL</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">42
// alternatively, as of PHP 7.0.0:</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> (<span style="color: rgba(128, 0, 128, 1)">$obj</span>->bar)(), <span style="color: rgba(255, 0, 255, 1)">PHP_EOL</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">42</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$obj</span>->bar();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">45</span></pre>
</div>
<p> 继承</p>
<p>类可以在声明中用 <em>extends</em> 关键字继承另一个类的方法和属性。<span style="color: rgba(204, 153, 255, 1)">PHP不支持多重继承,一个类只能继承一个基类</span></p>
<p>被继承的方法和属性可以通过用同样的名字重新声明被覆盖,覆盖后,可以通过 parent:: 来访问被覆盖的方法或属性。但是如果父类定义方法时使用了 final,则该方法不可被覆盖。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Father
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$aar</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> bar ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> 'father'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> testFinal ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> 'father'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> Son <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> father
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> bar ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> 'son'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> callFatherBar ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> parent::<span style="color: rgba(0, 0, 0, 1)">bar();
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Cannot override final method Father::testFinal()
// public function testFinal()
// {
// }
//如果父类定义是设置了final 则父类方法均不能覆盖 final class Father
//属性无final的概念</span>
<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> (<span style="color: rgba(0, 0, 255, 1)">new</span> Son())->bar();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">son</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> (<span style="color: rgba(0, 0, 255, 1)">new</span> Son())->callFatherBar();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">father</span></pre>
</div>
<p>当覆盖方法时,参数必须保持一致否则 PHP 将发出 <code>E_STRICT</code> 级别的错误信息。但构造函数例外,构造函数可在被覆盖时使用不同的参数</p>
<p>获取完全限定名称 php5.5+</p>
<p>::class</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">namespace NS {
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ClassName
{
}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> ClassName::<span style="color: rgba(0, 0, 255, 1)">class</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">NS\ClassName</span>
}</pre>
</div>
<p>变量</p>
<p>类的变量成员叫做“属性”,或者叫“字段”、“特征”,在本文档统一称为“属性”</p>
<p>属性声明是由关键字 <em>public</em>,<em>protected</em> 或者 <em>private</em> 开头,然后跟一个普通的变量声明来组成。属性中的变量可以初始化,但是初始化的值必须是常数,不能时表达式</p>
<p>为了兼容还可以用var 来声明属性,后面还可以跟上三p,如没有跟,默认为public</p>
<p>在类的方法内获取属性</p>
<p>$this->property//非静态</p>
<p>self::$property//静态</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SimpleClass
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 正确的属性声明</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var6</span> =<span style="color: rgba(0, 0, 0, 1)"> myConstant;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var7</span> = <span style="color: rgba(0, 0, 255, 1)">array</span>(<span style="color: rgba(0, 0, 255, 1)">true</span>, <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在 PHP 5.3.0 及之后,下面的声明也正确,//nowdoc方式相当于单引号</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var8</span> = <<<'EOD'<span style="color: rgba(0, 0, 0, 1)">
hello world
EOD;
}</span></pre>
</div>
<p> 常量</p>
<p class="para">常量的值必须是一个定值,不能是变量,类属性,数学运算的结果或函数调用。</p>
<p class="para">php5.6+ 可为表达式</p>
<p class="para">接口(interface)中也可以定义常量。</p>
<p class="para">自 PHP 5.3.0 起,可以用一个变量来动态调用类。但该变量的值不能为关键字(如 <em>self</em>,<em>parent</em> 或 <em>static</em>)</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyClass
{
</span><span style="color: rgba(0, 0, 255, 1)">const</span> <span style="color: rgba(0, 128, 128, 1)">constant</span> = 'constant value'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> showConstant() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span>self::<span style="color: rgba(0, 128, 128, 1)">constant</span> . "\n"<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> MyClass::<span style="color: rgba(0, 128, 128, 1)">constant</span> . "\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$classname</span> = "MyClass"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$classname</span>::<span style="color: rgba(0, 128, 128, 1)">constant</span> . "\n"; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 自 5.3.0 起,不能为关键字(如 self,parent 或 static)</span>
<span style="color: rgba(128, 0, 128, 1)">$class</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MyClass();
</span><span style="color: rgba(128, 0, 128, 1)">$class</span>-><span style="color: rgba(0, 0, 0, 1)">showConstant();
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$class</span>::<span style="color: rgba(0, 128, 128, 1)">constant</span>."\n"; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 自 PHP 5.3.0 起</span></pre>
</div>
<p>静态数据:不包含任何变量的数据</p>
<p>类的变量和常量申明为静态数据</p>
<p>和 heredoc 不同,nowdoc 可以用在任何静态数据中。</p>
<p>自动加载</p>
<p>为了解决新建每个类时,需要手动inlcude问题,使用<span class="function">spl_autoload_register() 函数可以注册任意数量的自动加载器。</span></p>
<p><span class="function">通过注册自动加载器,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类??</span></p>
<p><span class="function">__autoload()也有类似功能,后续版本要弃用,尽量不使用<br></span></p>
<p> <span class="methodname">spl_autoload_register ([ <span class="methodparam"><span class="type">callable <code class="parameter">$autoload_function</code> [, <span class="methodparam"><span class="type">bool <code class="parameter">$throw</code><span class="initializer"> = true //注册失败是否抛出异常[, <span class="methodparam"><span class="type">bool <code class="parameter">$prepend</code><span class="initializer"> = false ]//是否放在函数队列最前]] ) : <span class="type">bool</span></span></span></span></span></span></span></span></span></span></p>
<p>多次注册,函数内有个自动序列,prepend控制是否放在队列最前</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">TestAutoLoad.inc.php</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TestAutoLoad
{
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$var</span> = 'abc'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> self::<span style="color: rgba(128, 0, 128, 1)">$var</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">index.php</span>
<span style="color: rgba(0, 0, 255, 1)">function</span> __autoload (<span style="color: rgba(128, 0, 128, 1)">$className</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">__autoload() is deprecated, use spl_autoload_register() instead</span>
<span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 0, 255, 1)">include</span> "./<span style="color: rgba(128, 0, 128, 1)">$className</span>.inc.php"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TestAutoload();
</span><span style="color: rgba(0, 0, 255, 1)">function</span> myAutoload (<span style="color: rgba(128, 0, 128, 1)">$className</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">include</span> "./<span style="color: rgba(128, 0, 128, 1)">$className</span>.inc.php"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span> myAutoload1 (<span style="color: rgba(128, 0, 128, 1)">$className</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">include</span> "./<span style="color: rgba(128, 0, 128, 1)">$className</span>.inc.php"<span style="color: rgba(0, 0, 0, 1)">;
}
spl_autoload_register(</span>'myAutoload', <span style="color: rgba(0, 0, 255, 1)">true</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">spl_autoload_register自动加入到__autoload函数队列</span>
<span style="color: rgba(0, 0, 0, 1)">
spl_autoload_register(</span>'myAutoload1', <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> TestAutoload();
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> TestAutoload();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">并没有抛出多次include的异常,猜测函数内部判断,只include了一次</span></pre>
</div>
<p>传入数组</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> ClassAutoloader {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct() {
spl_autoload_register(</span><span style="color: rgba(0, 0, 255, 1)">array</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span>, 'loader'<span style="color: rgba(0, 0, 0, 1)">));
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">function</span> loader(<span style="color: rgba(128, 0, 128, 1)">$className</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'Trying to load ', <span style="color: rgba(128, 0, 128, 1)">$className</span>, ' via ', <span style="color: rgba(255, 0, 255, 1)">__METHOD__</span>, "()\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">include</span> <span style="color: rgba(128, 0, 128, 1)">$className</span> . '.php'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$autoloader</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ClassAutoloader();
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Class1();
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> Class2();</pre>
</div>
<p>自5.3起,可以使用匿名函数</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 或者,自 PHP 5.3.0 起可以使用一个匿名函数</span>
spl_autoload_register(<span style="color: rgba(0, 0, 255, 1)">function</span> (<span style="color: rgba(128, 0, 128, 1)">$class</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">include</span> 'classes/' . <span style="color: rgba(128, 0, 128, 1)">$class</span> . '.class.php'<span style="color: rgba(0, 0, 0, 1)">;
});</span></pre>
</div>
<p>自5.3起,亦可以使用类中静态方法</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">namespace Foobar;
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Foo {
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> test(<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">print</span> '[['. <span style="color: rgba(128, 0, 128, 1)">$name</span> .']]'<span style="color: rgba(0, 0, 0, 1)">;
}
}
spl_autoload_register(__NAMESPACE__ </span>.'\Foo::test'); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 自 PHP 5.3.0 起</span>
<span style="color: rgba(0, 0, 255, 1)">new</span> InexistentClass;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">[]</span></pre>
</div>
<p>接口亦可以</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ITest.php</span>
<span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> ITest
{
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">index.php</span>
spl_autoload_register(<span style="color: rgba(0, 0, 255, 1)">function</span> (<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">include</span> "<span style="color: rgba(128, 0, 128, 1)">$name</span>.php"<span style="color: rgba(0, 0, 0, 1)">;
});
</span><span style="color: rgba(0, 0, 255, 1)">class</span> Foo <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> ITest {
}</span></pre>
</div>
<p> 异常处理</p>
<div class="cnblogs_code">
<pre>spl_autoload_register(<span style="color: rgba(0, 0, 255, 1)">function</span> (<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "Want to load <span style="color: rgba(128, 0, 128, 1)">$name</span>.\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">Exception</span>("Unable to load <span style="color: rgba(128, 0, 128, 1)">$name</span>."<span style="color: rgba(0, 0, 0, 1)">);
});
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> NonLoadableClass();
} </span><span style="color: rgba(0, 0, 255, 1)">catch</span> (<span style="color: rgba(0, 0, 255, 1)">Exception</span> <span style="color: rgba(128, 0, 128, 1)">$e</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$e</span>->getMessage(), "\n"<span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<div class="cnblogs_code">
<pre>spl_autoload_register(<span style="color: rgba(0, 0, 255, 1)">function</span> (<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "Want to load <span style="color: rgba(128, 0, 128, 1)">$name</span>.\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> MissingException("Unable to load <span style="color: rgba(128, 0, 128, 1)">$name</span>.");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Want to load MissingException. Uncaught Error: Class 'MissingException' not found </span>
<span style="color: rgba(0, 0, 0, 1)">});
</span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> NonLoadableClass();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Want to load NonLoadableClass.</span>
} <span style="color: rgba(0, 0, 255, 1)">catch</span> (<span style="color: rgba(0, 0, 255, 1)">Exception</span> <span style="color: rgba(128, 0, 128, 1)">$e</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$e</span>->getMessage(), "\n"<span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p> 构造函数及构析函数r</p>
<p>PHP 5 允行开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。</p>
<p>__construct($arg...):void</p>
<p>如果子类中定义了构造函数,不会隐式的调用父类的构造函数,需要用parent::__construct()调用,如果子类没有构造函数,父类的构造函数将和普通函数一样被子类继承。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Father
{
</span><span style="color: rgba(0, 0, 255, 1)">function</span> __construct ()<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">不可为private</span>
<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'Father'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> Child <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Father
{ </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当Child无构造函数时,自动调用父类的 Father</span>
<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'Child'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> callFatherConstruct ()
{
parent</span>::<span style="color: rgba(0, 0, 0, 1)">__construct();
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> Child;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Child </span>
<span style="color: rgba(128, 0, 128, 1)">$obj</span>->callFatherConstruct();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Father</span></pre>
</div>
<p>自 PHP 5.3.3 起,在命名空间中,与类名同名的方法不再作为构造函数。这一改变不影响不在命名空间中的类。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">namespace Foo;
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Bar {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Bar() {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> treated as constructor in PHP 5.3.0-5.3.2
// treated as regular method as of PHP 5.3.3</span>
<span style="color: rgba(0, 0, 0, 1)"> }
}</span></pre>
</div>
<p>析构函数不是构析函数。。手动狗头 </p>
<p>PHP 5 引入了析构函数的概念,这类似于其它面向对象的语言,如 C++。析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyDestructableClass {
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct() {
</span><span style="color: rgba(0, 0, 255, 1)">print</span> "In constructor\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->name = "MyDestructableClass"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __destruct() {
</span><span style="color: rgba(0, 0, 255, 1)">print</span> "Destroying " . <span style="color: rgba(128, 0, 128, 1)">$this</span>->name . "\n"<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> MyDestructableClass(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">In constructor</span>
<span style="color: rgba(0, 0, 255, 1)">unset</span>(<span style="color: rgba(128, 0, 128, 1)">$obj</span>); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Destroying MyDestructableClass</span>
<span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">null</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Destroying MyDestructableClass</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> 6666; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">6666
//Destroying MyDestructableClass 程序结束后,释放所有变量</span></pre>
</div>
<p>exit 和die也生效</p>
<p>析构函数在脚本关闭时调用,此时所有的 HTTP 头信息已经发出!!脚本关闭时的工作目录有可能和在 SAPI(如 apache)中时不同??!!</p>
<p>析构函数子类的策略与构造函数相同</p>
<p>试图在析构函数(在脚本终止时被调用)中抛出一个异常会导致致命错误!!</p>
<p>重点:访问控制(可见性)</p>
<p>三个关键字控制 public 公有;protected 受保护;private 私有的</p>
<p>public:可以在任何地方被访问</p>
<p>protected:可以被自身或其子类和父类访问</p>
<p>private:只能被其定义所在的类访问</p>
<p>属性的访问控制</p>
<p>类属性必须定义为三种控制之一,如为var,则视为公有</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Father
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$public</span> = "fatherPublic\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(128, 0, 128, 1)">$protected</span> = "fatherProtected\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$private</span> = "fatherPrivate\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$private1</span> = "fatherPrivate1\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> showAttribution()
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> var_dump($this);</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 255, 1)">protected</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">private1;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> Me <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Father
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 可以对 public 和 protected 进行重定义,但 private 而不能,如下var_dump将保留Me:private,不知如何访问到这个属性</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$public</span> = "mePublic\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(128, 0, 128, 1)">$protected</span> = "meProtected\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$private</span> = "mePrivate\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当重写showAttribution 方法时,$this->private访问到了Me:private</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> showAttribution()
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> var_dump($this);结果与继承的showAttribution一致</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 255, 1)">protected</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">private1;
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">var_dump()</span><span style="color: rgba(0, 128, 0, 1)">
/*</span><span style="color: rgba(0, 128, 0, 1)">object(Me)#1 (4) {
["public"]=> string(9) "mePublic "
["protected":protected]=> string(12) "meProtected "
["private":"Me":private]=> string(10) "mePrivate "
["private1":"Father":private]=> string(14) "fatherPrivate "
["private":"Father":private]=> string(14) "fatherPrivate "
}
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(128, 0, 128, 1)">$me</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Me;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$me</span>-><span style="color: rgba(0, 0, 255, 1)">public</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">mePublic
// echo $me->protected;//Uncaught Error: Cannot access protected property
//echo $me->private;//Uncaught Error: Cannot access private property</span>
<span style="color: rgba(128, 0, 128, 1)">$me</span>->showAttribution();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">mePublic meProtected mePrivate </span>
<span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">结论
可以对 public 和 protected 和private 进行重定义,public 和 protected直接覆盖
而继承而来的方法访问private的是父类的,自己的方法访问private是重写后的
</span><span style="color: rgba(0, 128, 0, 1)">*/</span></pre>
</div>
<p>方法的访问控制</p>
<p>类中的方法可以被定义为公有,私有或受保护。如果没有设置这些关键字,则该方法默认为公有</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Father
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct () {}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myPublic ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "fatherPublic</br>"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myProtected ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "fatherProtected</br>"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myPrivate ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "fatherPrivate</br>"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> foo ()
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">myPublic();
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">myProtected();
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">myPrivate();
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$father</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Father();
</span><span style="color: rgba(128, 0, 128, 1)">$father</span>->myPublic();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通过
//$father->myProtected();//Uncaught Error: Call to protected method
//$father->myPrivate();//Uncaught Error: Call to private method</span>
<span style="color: rgba(128, 0, 128, 1)">$father</span>->foo();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">通过</span>
<span style="color: rgba(0, 0, 255, 1)">class</span> Me <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Father
{
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> foo1()
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">myPublic();
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">myProtected();
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">myPrivate();
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myPublic ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "mePublic</br>"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myProtected ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "meProtected</br>"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myPrivate ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "mePrivate</br>"<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$me</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Me();
</span><span style="color: rgba(128, 0, 128, 1)">$me</span>->foo1();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">mePublic meProtected mePrivate</span>
<span style="color: rgba(128, 0, 128, 1)">$me</span>->foo();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">mePublic meProtected fatherPrivate</span></pre>
</div>
<p>其他对象的访问控制</p>
<p>同一个类的对象即使不是同一个实例也可以互相访问对方的私有与受保护成员。</p>
<p>这是由于在这些对象的内部具体实现的细节都是已知的。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __construct(<span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->b = <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myPrivate ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'private'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> showPrivate (A <span style="color: rgba(128, 0, 128, 1)">$c</span><span style="color: rgba(0, 0, 0, 1)">)
{ </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">改变私有属性</span>
<span style="color: rgba(128, 0, 128, 1)">$c</span>->b = 'hello'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$c</span>-><span style="color: rgba(0, 0, 0, 1)">b);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">调用私有方法</span>
<span style="color: rgba(128, 0, 128, 1)">$c</span>-><span style="color: rgba(0, 0, 0, 1)">myPrivate();
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$test</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> A('test');<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">hello</span>
<span style="color: rgba(128, 0, 128, 1)">$test</span>->showPrivate(<span style="color: rgba(0, 0, 255, 1)">new</span> A('other'));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">private</span></pre>
</div>
<p> 继承</p>
<p>继承将会影响到类与类,对象与对象之间的关系。</p>
<p>当扩展一个类,子类就会继承父类所有公有的和受保护的方法。除非子类覆盖了父类的方法,被继承的方法都会保留其原有功能。</p>
<p>继承对于功能的设计和抽象是非常有用的,而且对于类似的对象增加新功能就无须重新再写这些公用的功能。</p>
<p>除非使用了自动加载,否则一个类必须在使用之前被定义。如果一个类扩展了另一个,则父类必须在子类之前被声明。此规则适用于类继承其它类与接口</p>
<p>范围解释操作符 ::</p>
<p>用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法</p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">const</span> MYCONST = 123<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$myStatic</span> = 'A static var'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = 666<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myFunc ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'A::myFunc'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> b ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'fun b'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">访问常量</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> A::<span style="color: rgba(0, 0, 0, 1)">MYCONST;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'A'::<span style="color: rgba(0, 0, 0, 1)">MYCONST;
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = 'A'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$a</span>::<span style="color: rgba(0, 0, 0, 1)">MYCONST;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">访问静态成员</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$a</span>::<span style="color: rgba(128, 0, 128, 1)">$a</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">666</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$a</span>::<span style="color: rgba(0, 0, 0, 1)">b();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">self parentstatic 三个特殊的关键字用于在类定义的内部对其属性或方法进行访问</span>
<span style="color: rgba(0, 0, 255, 1)">class</span> B <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$myStatic</span> = 'my static var'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> show ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> parent::<span style="color: rgba(0, 0, 0, 1)">MYCONST;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> self::<span style="color: rgba(128, 0, 128, 1)">$myStatic</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">my static var</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 0, 255, 1)">static</span>::<span style="color: rgba(128, 0, 128, 1)">$myStatic</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">效果等同上</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> parent::<span style="color: rgba(128, 0, 128, 1)">$myStatic</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">A static var</span>
<span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">覆盖了父类的定义</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myFunc ()
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">依旧可以调用父类中被覆盖的方法</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> 'B::myFunc'<span style="color: rgba(0, 0, 0, 1)">;
parent</span>::<span style="color: rgba(0, 0, 0, 1)">myFunc();
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$b</span> = 'B'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$b</span>::<span style="color: rgba(0, 0, 0, 1)">show();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">当一个子类覆盖其父类中的方法时,PHP 不会调用父类中已被覆盖的方法。是否调用父类的方法取决于子类。这种机制也作用于构造函数和析构函数,重载以及魔术方法</span>
<span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> B();
</span><span style="color: rgba(128, 0, 128, 1)">$b</span>->myFunc();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">B::myFunc A::myFunc</span></pre>
</div>
<p> static静态关键字</p>
<p>作用一:申明</p>
<p>声明类属性或方法为静态,就可以不实例化类而直接访问</p>
<p>静态属性不能通过一个类已实例化的对象来访问(但静态方法可以),静态属性不可以由对象通过 -> 操作符来访问。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$myStatic</span> = 'A static var'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myFunc ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'A::myFunc'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A();
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$a</span>->myStatic;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> Accessing static property A::$myStatic as non static</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->myFunc();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">有效,A::myFunc</span></pre>
</div>
<p>由于静态方法不需要通过对象即可调用,所以伪变量 <var class="varname"><var class="varname">$this</var></var> 在静态方法中不可用</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$myStatic</span> = 'A static var'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> myFunc ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>->myStatic;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Uncaught Error: Using $this when not in object context </span>
<span style="color: rgba(0, 0, 0, 1)"> }
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A();
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->myFunc();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Uncaught Error: Using $this when not in object context </span></pre>
</div>
<p>就像其它所有的 PHP 静态变量一样,静态属性只能被初始化为文字或常量,不能使用表达式。所以可以把静态属性初始化为整数或数组,但不能初始化为另一个变量或函数返回值,也不能指向一个对象。</p>
<p>抽象类 php5+</p>
<p>定义为抽象的类不能被实例化</p>
<p>任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的;</p>
<p>被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现;</p>
<p>继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;</p>
<p><span style="color: rgba(204, 153, 255, 1)">这些方法的访问控制必须和父类中一样(或者更为宽松)</span>!!</p>
<p>此外方法的调用方式必须匹配,即类型和所需参数数量必须一致,子类可多设置有默认值的参数</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Foo
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$my_static</span> = 'foo'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">强制要求子类定义这类方法</span>
<span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">function</span> protectedFunc (<span style="color: rgba(128, 0, 128, 1)">$arg</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> publicFunc (...<span style="color: rgba(128, 0, 128, 1)">$arg</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">参数数量要一致
//普通方法(非抽象方法)</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> nomalFunc (<span style="color: rgba(128, 0, 128, 1)">$arg</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'nomalFunc'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> Foo1 <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Foo
{ </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 我们的子类可以定义父类签名中不存在的可选参数,及默认值</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> protectedFunc (<span style="color: rgba(128, 0, 128, 1)">$arg</span>, <span style="color: rgba(128, 0, 128, 1)">$arg1</span> = 123, <span style="color: rgba(128, 0, 128, 1)">$arg2</span> = 456)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">大于等于protected的控制方式</span>
<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "protectedFunc\n<span style="color: rgba(128, 0, 128, 1)">$arg</span>\n<span style="color: rgba(128, 0, 128, 1)">$arg1</span>\n<span style="color: rgba(128, 0, 128, 1)">$arg2</span>"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span>publicFunc (...<span style="color: rgba(128, 0, 128, 1)">$arg</span>)<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">//参数数量要一致</span>
<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'publicFunc '.<span style="color: rgba(128, 0, 128, 1)">$arg</span>;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$foo1</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Foo1();
</span><span style="color: rgba(128, 0, 128, 1)">$foo1</span>->publicFunc('test', 'test1'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$foo1</span>->protectedFunc('test', 'test1');</pre>
</div>
<p>接口</p>
<p> 使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。</p>
<p>接口中定义的所有方法都必须是<span style="color: rgba(204, 153, 255, 1)">公有</span>,其中定义所有的方法都是空的</p>
<p>实现(implements)</p>
<p>要实现一个接口,使用 <em>implements</em> 操作符。<span style="color: rgba(204, 153, 255, 1)">类中必须实现接口中定义的所有方法</span>,否则会报一个致命错误。<span style="color: rgba(204, 153, 255, 1)">类可以实现多个接口,用逗号来分隔多个接口的名称</span>。</p>
<p>类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误</p>
<p>接口也可以继承,通过使用 extends 操作符</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">经典例子</span>
<span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> Iter
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> setValue (<span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getValue ();
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实现接口</span>
<span style="color: rgba(0, 0, 255, 1)">class</span> A <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> Iter
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> setValue (<span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->val = <span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getValue ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">val;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A();
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->setValue('xxx'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->getValue();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">xxx</span></pre>
</div>
<p>实现多个接口</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实现多个接口 </span>
<span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> Iter
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> setValue (<span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getValue ();
}
</span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> Ext
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> varDumpValue ();
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实现接口</span>
<span style="color: rgba(0, 0, 255, 1)">class</span> A <span style="color: rgba(0, 0, 255, 1)">implements</span> Iter,<span style="color: rgba(0, 0, 0, 1)"> Ext
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> setValue (<span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->val = <span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getValue ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">val;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> varDumpValue ()
{
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">val);
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A();
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->setValue('xxx'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->getValue();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">xxx</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->varDumpValue();</pre>
</div>
<p>可扩充接口,继承</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">可扩充接口 </span>
<span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> Iter
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> setValue (<span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getValue ();
}
</span><span style="color: rgba(0, 0, 255, 1)">interface</span> Ext <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Iter
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> varDumpValue ();
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实现接口</span>
<span style="color: rgba(0, 0, 255, 1)">class</span> A <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> Ext
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> setValue (<span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->val = <span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getValue ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">val;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> varDumpValue ()
{
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">val);
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A();
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->setValue('xxx'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->getValue();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">xxx</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->varDumpValue();</pre>
</div>
<p><span style="color: rgba(204, 153, 255, 1)">参数类型如有限定,也必须一致</span>,string对应string<br>// public function baz(Baz $baz);//interface<br>// public function baz(Foo $foo);//class</p>
<p>接口中也可以定义常量,但是不能被子类或子接口所覆盖,也必须是公有的</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">const</span> B = '567'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> A::<span style="color: rgba(0, 0, 0, 1)">B;
</span><span style="color: rgba(0, 0, 255, 1)">class</span> B <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">const</span> B = '789';<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">不能被子类或子接口所覆盖</span>
<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> B::B;</pre>
</div>
<p>Trait</p>
<p>自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait,实现类的水平多次继承</p>
<p>用法类内用use</p>
<p>优先级 当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法,<span style="color: rgba(204, 153, 255, 1)">由于优先级而trait内方法生效,此方法必须public</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">trait A
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'Trait'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> B
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'classB'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> C <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> B
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'classC'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">use</span> A;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">classC</span>
<span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(128, 0, 128, 1)">$c</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> C();
</span><span style="color: rgba(128, 0, 128, 1)">$c</span>->funcA();</pre>
</div>
<p><span style="color: rgba(204, 153, 255, 1)">trait 和 类 的名字不能重复</span></p>
<p>多此trait,trait间方法不能重名</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">trait A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'traitA'<span style="color: rgba(0, 0, 0, 1)">;
}
}
trait B
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcB ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'traitB'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> C
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'classC'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> D <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> C
{
</span><span style="color: rgba(0, 0, 255, 1)">use</span> A,<span style="color: rgba(0, 0, 0, 1)"> B;
}
</span><span style="color: rgba(128, 0, 128, 1)">$d</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> D();
</span><span style="color: rgba(128, 0, 128, 1)">$d</span>->funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitA</span>
<span style="color: rgba(128, 0, 128, 1)">$d</span>->funcB();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitB</span></pre>
</div>
<p>如有重名冲突,需要使用 <em>insteadof</em> 操作符来明确指定使用冲突方法中的哪一个</p>
<p>1、排除冲突,insteadOf</p>
<p>2、保留冲突,as</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">trait A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'traitA'<span style="color: rgba(0, 0, 0, 1)">;
}
}
trait B
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'traitB'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> C
{
</span><span style="color: rgba(0, 0, 255, 1)">use</span> A,<span style="color: rgba(0, 0, 0, 1)"> B
{
A</span>::<span style="color: rgba(0, 0, 0, 1)">funcA insteadOf B;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> D
{
</span><span style="color: rgba(0, 0, 255, 1)">use</span> A,<span style="color: rgba(0, 0, 0, 1)"> B
{
A</span>::<span style="color: rgba(0, 0, 0, 1)">funcA insteadOf B;
B</span>::funcA <span style="color: rgba(0, 0, 255, 1)">as</span><span style="color: rgba(0, 0, 0, 1)"> BfuncA;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$c</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> C();
</span><span style="color: rgba(128, 0, 128, 1)">$c</span>->funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitA</span>
<span style="color: rgba(128, 0, 128, 1)">$d</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> D();
</span><span style="color: rgba(128, 0, 128, 1)">$d</span>->funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitA</span>
<span style="color: rgba(128, 0, 128, 1)">$d</span>->BfuncA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitB</span></pre>
</div>
<p> as 还可以修改方法的控制方式</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">trait A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'traitA'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> C
{
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> A
{
A</span>::funcA <span style="color: rgba(0, 0, 255, 1)">as</span> <span style="color: rgba(0, 0, 255, 1)">protected</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> D
{
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> A
{
funcA </span><span style="color: rgba(0, 0, 255, 1)">as</span> <span style="color: rgba(0, 0, 255, 1)">protected</span><span style="color: rgba(0, 0, 0, 1)"> AfuncA;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$c</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> C();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">$c->funcA();//错误,funcA已经时protected</span>
<span style="color: rgba(128, 0, 128, 1)">$d</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> D();
</span><span style="color: rgba(128, 0, 128, 1)">$d</span>->funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitA</span>
<span style="color: rgba(128, 0, 128, 1)">$d</span>->AfuncA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">报错,别名是protected,但这并不影响原名的使用</span></pre>
</div>
<p>嵌套trait</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">trait A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'traitA'<span style="color: rgba(0, 0, 0, 1)">;
}
}
trait B
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcB ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'traitB'<span style="color: rgba(0, 0, 0, 1)">;
}
}
trait C
{
</span><span style="color: rgba(0, 0, 255, 1)">use</span> A,<span style="color: rgba(0, 0, 0, 1)"> B;
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> D
{
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> C;
}
</span><span style="color: rgba(128, 0, 128, 1)">$d</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> D();
</span><span style="color: rgba(128, 0, 128, 1)">$d</span>->funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitA</span>
<span style="color: rgba(128, 0, 128, 1)">$d</span>->funcB();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitB</span></pre>
</div>
<p>为了对使用的类施加强制要求,trait 支持抽象方法的使用</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">trait A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'traitA'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">abstract</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcB ();
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> D
{
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcB ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'funcB'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$d</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> D();
</span><span style="color: rgba(128, 0, 128, 1)">$d</span>->funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">traitA</span>
<span style="color: rgba(128, 0, 128, 1)">$d</span>->funcB();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">funcB</span></pre>
</div>
<p>trait类方法的静态变量和方法及属性的用法</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">trait Counter {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">定义属性</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$a</span> = 123<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> inc() {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">静态变量</span>
<span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$c</span> = 0<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$c</span> = <span style="color: rgba(128, 0, 128, 1)">$c</span> + 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "<span style="color: rgba(128, 0, 128, 1)">$c</span>\n"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">静态方法</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> funcA ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 'static func'<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Trait 定义了一个属性后,类就不能定义同样名称的属性
//属性是兼容的(同样的访问可见度、初始默认值) php7+ 不报错
//不兼容致命错误</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> C1 {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$a</span> = 123;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">必须完全相同,有何意义?</span>
<span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Counter;
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> C2 {
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> Counter;
}
</span><span style="color: rgba(128, 0, 128, 1)">$o</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> C1(); <span style="color: rgba(128, 0, 128, 1)">$o</span>->inc(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> echo 1</span>
<span style="color: rgba(128, 0, 128, 1)">$p</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> C2(); <span style="color: rgba(128, 0, 128, 1)">$p</span>->inc(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> echo 1</span>
<span style="color: rgba(128, 0, 128, 1)">$q</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> C2(); <span style="color: rgba(128, 0, 128, 1)">$q</span>->inc(); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> echo 2 //静态变量</span>
<span style="color: rgba(128, 0, 128, 1)">$o</span>::funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">static func</span>
Counter::funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">static func</span>
C1::funcA();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">static func</span></pre>
</div>
<p> php7开始支持匿名类</p>
<p>匿名类很有用,可以创建一次性的简单对象。考虑消耗吗</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">php7 -</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> B
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> c ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 666<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span> a (B <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(128, 0, 128, 1)">$b</span>-><span style="color: rgba(0, 0, 0, 1)">c();
}
a(</span><span style="color: rgba(0, 0, 255, 1)">new</span> B);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">666
//php7+</span>
<span style="color: rgba(0, 0, 255, 1)">function</span> a (<span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(128, 0, 128, 1)">$b</span>-><span style="color: rgba(0, 0, 0, 1)">c();
}
a(</span><span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> c ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> 777<span style="color: rgba(0, 0, 0, 1)">;
}
});</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">777</span></pre>
</div>
<p>匿名可继承可实现</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SomeClass {}
</span><span style="color: rgba(0, 0, 255, 1)">interface</span><span style="color: rgba(0, 0, 0, 1)"> SomeInterface {}
trait SomeTrait {}
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">class</span> (10) <span style="color: rgba(0, 0, 255, 1)">extends</span> SomeClass <span style="color: rgba(0, 0, 255, 1)">implements</span><span style="color: rgba(0, 0, 0, 1)"> SomeInterface {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$num</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __construct (<span style="color: rgba(128, 0, 128, 1)">$num</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->num = <span style="color: rgba(128, 0, 128, 1)">$num</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">use</span><span style="color: rgba(0, 0, 0, 1)"> SomeTrait;
});
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">object(class@anonymous)#1 (1) { ["num":"class@anonymous":private]=> int(10) }</span></pre>
</div>
<p>匿名类被嵌套进普通 Class 后,不能访问这个外部类(Outer class)的 private(私有)、protected(受保护)方法或者属性,作用域不在这个普通类内,是为独立作用域</p>
<p>为了解决这个矛盾:</p>
<p>使用extends 获得protected的属性和方法;</p>
<p>使用构造器(即构造函数)传进private的属性和方法。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Outer
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$prop1</span> = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(128, 0, 128, 1)">$prop2</span> =2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> func1 ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> 3<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> func2 ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">class</span> (<span style="color: rgba(128, 0, 128, 1)">$this</span>->prop1) <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> Outer {
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$prop3</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __construct (<span style="color: rgba(128, 0, 128, 1)">$prop</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->prop3 = <span style="color: rgba(128, 0, 128, 1)">$prop</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> func3 ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>->prop2 + <span style="color: rgba(128, 0, 128, 1)">$this</span>->prop3 + <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">func1();
}
};
}
}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> (<span style="color: rgba(0, 0, 255, 1)">new</span> Outer)->func2()->func3();</pre>
</div>
<p>声明的同一个匿名类,所创建的对象都是这个类的实例,有一个相同的隐式名字</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> a ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> {};
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">匿名类的名称是通过引擎赋予的,不用管这个名字,无实际意义</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 128, 128, 1)">get_class</span>(a()) === <span style="color: rgba(0, 128, 128, 1)">get_class</span><span style="color: rgba(0, 0, 0, 1)">(a())){
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 128, 128, 1)">get_class</span>(a());<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">class@anonymousE:\mc\webroot\index.php000002767DE00029</span>
}</pre>
</div>
<p> 类的重载</p>
<p>指动态地<q class="quote">创建</q>类属性和方法。我们是通过魔术方法(magic methods)来实现的。</p>
<p>当调用当前环境下未定义或不可见(访问控制)的类属性或方法时,重载方法会被调用。</p>
<p><span style="color: rgba(204, 153, 255, 1)">所有的重载方法都必须被声明为 </span><em><span style="color: rgba(204, 153, 255, 1)">public</span>。</em></p>
<p><em>目的是为了调用不用访问的属性和方法吗?</em></p>
<p>!!这些魔术方法的参数都不能通过引用传递</p>
<p>!!PHP中的<q class="quote">重载</q>与其它绝大多数面向对象语言不同。传统的<q class="quote">重载</q>是用于提供多个同名的类方法,但各方法的参数类型和个数不同。</p>
<p>属性的魔术方法</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> PropertyTest
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">被重载的数据保持在此</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$data</span> =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">重载不能用在可以访问的属性</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$declared</span> = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">只有从类外部访问这个属性时,重载才会发生</span>
<span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$hidden</span> = 2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">在给不可访问属性赋值时,__set() 会被调用</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __set (<span style="color: rgba(128, 0, 128, 1)">$name</span>, <span style="color: rgba(128, 0, 128, 1)">$value</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "Setting '<span style="color: rgba(128, 0, 128, 1)">$name</span>' to '<span style="color: rgba(128, 0, 128, 1)">$value</span>'\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->data[<span style="color: rgba(128, 0, 128, 1)">$name</span>] = <span style="color: rgba(128, 0, 128, 1)">$value</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">读取不可访问属性的值时,__get() 会被调用</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __get (<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "Getting '<span style="color: rgba(128, 0, 128, 1)">$name</span>'\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(0, 128, 128, 1)">array_key_exists</span>(<span style="color: rgba(128, 0, 128, 1)">$name</span>, <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">data)){
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>->data[<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">];
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果不存在此key,报错
//debug_backtrace()可返回当前环境,由此组装报错string</span>
<span style="color: rgba(128, 0, 128, 1)">$trace</span> = <span style="color: rgba(0, 128, 128, 1)">debug_backtrace</span><span style="color: rgba(0, 0, 0, 1)">();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">产生一个用户级别的error/warning/notice信息</span>
<span style="color: rgba(0, 128, 128, 1)">trigger_error</span>('Undefined property via __get(): ' . <span style="color: rgba(128, 0, 128, 1)">$name</span> .
' in ' . <span style="color: rgba(128, 0, 128, 1)">$trace</span>['file'] .
' on line ' . <span style="color: rgba(128, 0, 128, 1)">$trace</span>['line'],
<span style="color: rgba(255, 0, 255, 1)">E_USER_NOTICE</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">php5.1+可用isset和unset</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __isset (<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "Is '<span style="color: rgba(128, 0, 128, 1)">$name</span>' set?\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">isset</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span>->data[<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">]);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __unset (<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "Unsetting '<span style="color: rgba(128, 0, 128, 1)">$name</span>'\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">unset</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span>->data[<span style="color: rgba(128, 0, 128, 1)">$name</span><span style="color: rgba(0, 0, 0, 1)">]);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">只有从类外部访问这个属性时,重载才会发生</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> getHidden ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">hidden;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$test</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> PropertyTest ();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Undefined property via __get(): a in E:\mc\webroot\index.php on line 40</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$test</span>->a;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Getting 'a'</span>
<span style="color: rgba(128, 0, 128, 1)">$test</span>->a = 123;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Setting 'a' to '123'
//Getting 'a'</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$test</span>->a;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">123</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$test</span>->getHidden();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2 不会发生重载</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$test</span>->hidden;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Getting 'hidden' 发生重载 </span></pre>
</div>
<p>方法重载</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MethodTest
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __call (<span style="color: rgba(128, 0, 128, 1)">$name</span>,<span style="color: rgba(128, 0, 128, 1)">$arguments</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注意: $name 的值区分大小写</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> "Calling object method '<span style="color: rgba(128, 0, 128, 1)">$name</span>' "
. <span style="color: rgba(0, 128, 128, 1)">implode</span>(', ', <span style="color: rgba(128, 0, 128, 1)">$arguments</span>). "\n"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">php5.3+</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __callStatic (<span style="color: rgba(128, 0, 128, 1)">$name</span>, <span style="color: rgba(128, 0, 128, 1)">$arguments</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 注意: $name 的值区分大小写</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> "Calling static method '<span style="color: rgba(128, 0, 128, 1)">$name</span>' "
. <span style="color: rgba(0, 128, 128, 1)">implode</span>(', ', <span style="color: rgba(128, 0, 128, 1)">$arguments</span>). "\n"<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MethodTest;
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span>->runTest('1234');<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Call$ing object method 'runTest' 1234</span>
MethodTest::runTest('5678');<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Calling static method 'runTest' 5678</span></pre>
</div>
<p> 遍历对象</p>
<p>默认情况下,所有可见属性都将被用于遍历</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var1</span> = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var2</span> = 2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var3</span> = 3<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(128, 0, 128, 1)">$var4</span> = 4<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$var5</span> = 5<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> goThrough ()
{
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span> <span style="color: rgba(0, 0, 255, 1)">as</span> <span style="color: rgba(128, 0, 128, 1)">$key</span>=><span style="color: rgba(128, 0, 128, 1)">$val</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">print</span> "<span style="color: rgba(128, 0, 128, 1)">$key</span> => <span style="color: rgba(128, 0, 128, 1)">$val</span></br>"<span style="color: rgba(0, 0, 0, 1)">;
}
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span>(<span style="color: rgba(128, 0, 128, 1)">$a</span> <span style="color: rgba(0, 0, 255, 1)">as</span> <span style="color: rgba(128, 0, 128, 1)">$key</span> => <span style="color: rgba(128, 0, 128, 1)">$value</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 0, 255, 1)">print</span> "<span style="color: rgba(128, 0, 128, 1)">$kemy</span> => <span style="color: rgba(128, 0, 128, 1)">$value</span></br>"<span style="color: rgba(0, 0, 0, 1)">;
}</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">123</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> '<hr>'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->goThrough();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">12345</span></pre>
</div>
<p>更进一步,可以实现 <span class="interfacename"><span class="interfacename">Iterator 接口。可以让对象自行决定如何遍历以及每次遍历时那些值可用??</span></span></p>
<p><span class="interfacename"><span class="interfacename">迭代器</span></span></p>
<p><span class="interfacename"><span class="interfacename">魔术方法</span></span></p>
<p><span class="interfacename"><span class="interfacename">命令类方法时,不要与魔术方法名字冲突,除非是想用它</span></span></p>
<p>__开头,所以命名类方法时,不要这样命名</p>
<p>补充一些魔术方法的用法</p>
<p>__sleep()用于serialize()函数zhun调用时,序列化操作前调用此魔术方法,此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称和数组;</p>
<p>自定义序列化:方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用</p>
<p>__wakeup()与__sleep刚好相反,与unserialize()对应,用于预先准备对象需要的资源</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">一个数据库连接的类</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Connection
{
</span><span style="color: rgba(0, 0, 255, 1)">protected</span> <span style="color: rgba(128, 0, 128, 1)">$link</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$server</span>, <span style="color: rgba(128, 0, 128, 1)">$userName</span>, <span style="color: rgba(128, 0, 128, 1)">$password</span>, <span style="color: rgba(128, 0, 128, 1)">$db</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span><span style="color: rgba(0, 0, 255, 1)">function</span> __construct (<span style="color: rgba(128, 0, 128, 1)">$server</span>, <span style="color: rgba(128, 0, 128, 1)">$userName</span>, <span style="color: rgba(128, 0, 128, 1)">$password</span>, <span style="color: rgba(128, 0, 128, 1)">$db</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->server = <span style="color: rgba(128, 0, 128, 1)">$server</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->userName = <span style="color: rgba(128, 0, 128, 1)">$userName</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->password = <span style="color: rgba(128, 0, 128, 1)">$password</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->db = <span style="color: rgba(128, 0, 128, 1)">$db</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">connect();
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> connect ()
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->link = <span style="color: rgba(0, 128, 128, 1)">mysql_connect</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span>->server, <span style="color: rgba(128, 0, 128, 1)">$this</span>->userName, <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">password);
</span><span style="color: rgba(0, 128, 128, 1)">mysql_select_db</span>(<span style="color: rgba(128, 0, 128, 1)">$this</span>->db, <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">link);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __sleep ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> ['server','userName', 'password', 'db'];<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">仅保持有用信息</span>
<span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __wakeup ()
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->connect();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">sleep恢复之后所需要的操作</span>
<span style="color: rgba(0, 0, 0, 1)"> }
}</span></pre>
</div>
<p>__toString()方法用于一个类被当成字符串时应怎样回应</p>
<p>不能在__toString中抛出异常,php5.2起,可用于任何字符串环境</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">类当成string使用时 如何反应 toString</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Test
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$foo</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __construct (<span style="color: rgba(128, 0, 128, 1)">$foo</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->foo = <span style="color: rgba(128, 0, 128, 1)">$foo</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __toString ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">foo;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 0, 255, 1)">new</span> Test('waiting for');<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">waiting for</span></pre>
</div>
<p>__invoke方法php5.3+</p>
<p>当尝试以调用函数方式调用一个对象时,此方法会被自动调用</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> CallableClass
{
</span><span style="color: rgba(0, 0, 255, 1)">function</span> __invoke (<span style="color: rgba(128, 0, 128, 1)">$x</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$x</span><span style="color: rgba(0, 0, 0, 1)">);
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> CallableClass;
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span>(5);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">int(5) </span>
<span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(0, 128, 128, 1)">is_callable</span>(<span style="color: rgba(128, 0, 128, 1)">$obj</span>));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">bool(true)</span></pre>
</div>
<p> __set_state()</p>
<p>自 PHP 5.1.0 起当调用 <span class="function">var_export() 导出类时,此静态 方法会被调用</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var1</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var2</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$var4</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span> __set_state (<span style="color: rgba(128, 0, 128, 1)">$arr</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">下面全删了也一样的效果,有啥用??</span>
<span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span>->var1 = <span style="color: rgba(128, 0, 128, 1)">$arr</span>['var1'<span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span>->var2 = <span style="color: rgba(128, 0, 128, 1)">$arr</span>['var2'<span style="color: rgba(0, 0, 0, 1)">];
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span>->var4 = 55<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$obj</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->var1 = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->var2 = 2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">var_export</span>(<span style="color: rgba(128, 0, 128, 1)">$a</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">A::__set_state(array( 'var1' => 1, 'var2' => 2, 'var4' => NULL, ))</span>
<span style="color: rgba(0, 0, 255, 1)">eval</span>('$b = '.<span style="color: rgba(0, 128, 128, 1)">var_export</span>(<span style="color: rgba(128, 0, 128, 1)">$a</span>, <span style="color: rgba(0, 0, 255, 1)">true</span>).';'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">object(A)#2 (3) { ["var1"]=> int(1) ["var2"]=> int(2) ["var4":"A":private]=> int(55) }</span><span style="color: rgba(0, 128, 0, 1)">*/</span></pre>
</div>
<p>__debuginfo():array php5.6+</p>
<p>var_dump会把类的所有属性打出来,不管是什么访问控制</p>
<p>如果设置了debuginfo,则会先调用这个魔术方法,该显示什么,不该显示什么,该如何显示,由此控制</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var4</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __debugInfo ()
{
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> [
</span>'test' => <span style="color: rgba(128, 0, 128, 1)">$this</span>->var4**2<span style="color: rgba(0, 0, 0, 1)">
];
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->var4 = 42<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$a</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">object(A)#1 (1) { ["test"]=> int(1764) }</span></pre>
</div>
<p>final 关键字 php5.6+</p>
<p>如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。</p>
<p>我走到头了,不要想着继承我的(财产)</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BaseClass {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> test() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "BaseClass::test() called\n"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这里无论你是否将方法声明为final,都没有关系</span>
<span style="color: rgba(0, 0, 255, 1)">final</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> moreTesting() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "BaseClass::moreTesting() called\n"<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> ChildClass <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> BaseClass {
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 产生 Fatal error: Class ChildClass may not inherit from final class (BaseClass)</span></pre>
</div>
<p>对象的复制</p>
<p>对象复制可以通过 clone 关键字来完成(如果可能,这将调用对象的 __clone() 方法)。对象中的 __clone() 方法不能被直接调用</p>
<p>__clone()也是一种魔术方法</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> SubObject
{
</span><span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(128, 0, 128, 1)">$instances</span> = 0<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$instance</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __construct() {
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->instance = ++self::<span style="color: rgba(128, 0, 128, 1)">$instances</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __clone() {
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->instance = ++self::<span style="color: rgba(128, 0, 128, 1)">$instances</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyCloneable
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$object1</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$object2</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> __clone()
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 强制复制一份this->object, 否则仍然指向同一个对象</span>
<span style="color: rgba(128, 0, 128, 1)">$this</span>->object1 = <span style="color: rgba(0, 0, 255, 1)">clone</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">object1;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MyCloneable();
</span><span style="color: rgba(128, 0, 128, 1)">$obj</span>->object1 = <span style="color: rgba(0, 0, 255, 1)">new</span> SubObject();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1</span>
<span style="color: rgba(128, 0, 128, 1)">$obj</span>->object2 = <span style="color: rgba(0, 0, 255, 1)">new</span> SubObject();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2</span>
<span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(0, 0, 255, 1)">clone</span> <span style="color: rgba(128, 0, 128, 1)">$obj</span>->object2;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">由clone方法加上1,3</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$b</span>::<span style="color: rgba(128, 0, 128, 1)">$instances</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">3</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> SubObject::<span style="color: rgba(128, 0, 128, 1)">$instances</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">3</span>
<span style="color: rgba(128, 0, 128, 1)">$obj2</span> = <span style="color: rgba(0, 0, 255, 1)">clone</span> <span style="color: rgba(128, 0, 128, 1)">$obj</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">调用clone方法,再调用SubObject clone方法,加上1,4</span>
<span style="color: rgba(0, 128, 128, 1)">print_r</span>(<span style="color: rgba(128, 0, 128, 1)">$obj</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">1 2</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> '</br>'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">print_r</span>(<span style="color: rgba(128, 0, 128, 1)">$obj2</span>);<span style="color: rgba(0, 128, 0, 1)">//</span></pre>
</div>
<p> 对象比较</p>
<p>当使用比较运算符(<em>==</em>)比较两个对象变量时,比较的原则是:如果两个对象的属性和属性值 都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等</p>
<p>如果使用全等运算符(<em>===</em>),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$a</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">function</span> __construct (<span style="color: rgba(128, 0, 128, 1)">$a</span>, <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->a = <span style="color: rgba(128, 0, 128, 1)">$a</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>->b = <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span> compareObj (<span style="color: rgba(128, 0, 128, 1)">$a</span>, <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(128, 0, 128, 1)">$a</span> == <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(128, 0, 128, 1)">$a</span> === <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "===\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">else</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> "==\n"<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "<>\n"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> A(1,2<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> A(1,2<span style="color: rgba(0, 0, 0, 1)">);
compareObj(</span><span style="color: rgba(128, 0, 128, 1)">$a</span>, <span style="color: rgba(128, 0, 128, 1)">$b</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">==</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> A(1,2<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(128, 0, 128, 1)">$a</span><span style="color: rgba(0, 0, 0, 1)">;
compareObj(</span><span style="color: rgba(128, 0, 128, 1)">$a</span>, <span style="color: rgba(128, 0, 128, 1)">$b</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">===</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> A(1,2<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$b</span> = &<span style="color: rgba(128, 0, 128, 1)">$a</span><span style="color: rgba(0, 0, 0, 1)">;
compareObj(</span><span style="color: rgba(128, 0, 128, 1)">$a</span>, <span style="color: rgba(128, 0, 128, 1)">$b</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">===</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span> A(1,2<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(0, 0, 255, 1)">clone</span> <span style="color: rgba(128, 0, 128, 1)">$a</span><span style="color: rgba(0, 0, 0, 1)">;
compareObj(</span><span style="color: rgba(128, 0, 128, 1)">$a</span>, <span style="color: rgba(128, 0, 128, 1)">$b</span>);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">===
//PHP 5 会对对象的所有属性执行一个浅复制(shallow copy)。所有的引用属性 仍然会是一个指向原来的变量的引用。</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->a = 3<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$b</span>->a;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">3 !!!</span></pre>
</div>
<p>类型约束</p>
<p>如果一个类或接口指定了类型约束,则其所有的子类或实现也都如此</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">参数必须是B类实例</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> test (B <span style="color: rgba(128, 0, 128, 1)">$b</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$b</span>-><span style="color: rgba(0, 0, 255, 1)">var</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">参数必须是数组</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> testArr (<span style="color: rgba(0, 0, 255, 1)">array</span> <span style="color: rgba(128, 0, 128, 1)">$arr</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$arr</span><span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">第一个参数必须为递归类型, Traversable:检测一个类是否可以使用 foreach 进行遍历的接口</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> testInterface (Traversable <span style="color: rgba(128, 0, 128, 1)">$iterator</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(0, 128, 128, 1)">get_class</span>(<span style="color: rgba(128, 0, 128, 1)">$iterator</span><span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">回调类型</span>
<span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> testCallable (callable <span style="color: rgba(128, 0, 128, 1)">$callback</span>, <span style="color: rgba(128, 0, 128, 1)">$data</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 128, 128, 1)">call_user_func</span>(<span style="color: rgba(128, 0, 128, 1)">$callback</span>, <span style="color: rgba(128, 0, 128, 1)">$data</span><span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span> testString (<span style="color: rgba(0, 0, 255, 1)">string</span> <span style="color: rgba(128, 0, 128, 1)">$str</span><span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$str</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> B
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$var</span> = 'xffg'<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(128, 0, 128, 1)">$a</span>->test(<span style="color: rgba(0, 0, 255, 1)">new</span> B);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">xffg</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->testArr();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ArrayObject This class allows objects to work as arrays
//__construc(array())</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->testInterface(<span style="color: rgba(0, 0, 255, 1)">new</span> ArrayObject([]));<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">ArrayObject</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->testCallable('var_dump', '666');<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">string(3) "666"</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->testString('xxx');<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">xxx</span></pre>
</div>
<p>后期静态绑定</p>
<p> 自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类</p>
<p>如何使用</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> who() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(255, 0, 255, 1)">__CLASS__</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> test() {
self</span>::who();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">self的限制 A</span>
<span style="color: rgba(0, 0, 255, 1)">static</span>::who();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">后期静态绑定的用法 B</span>
<span style="color: rgba(0, 0, 0, 1)"> }
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> B <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> who() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(255, 0, 255, 1)">__CLASS__</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
B</span>::test();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">call A::test -> A::who or B::who</span></pre>
</div>
<p><span style="color: rgba(204, 153, 255, 1)"> 继承覆盖方法时,以更改访问控制,不可更改是否静态</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">方法为非静态时</span></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> who() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(255, 0, 255, 1)">__CLASS__</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> test() {
</span><span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">who();
</span><span style="color: rgba(0, 0, 255, 1)">static</span>::<span style="color: rgba(0, 0, 0, 1)">who();
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> B <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> who() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(255, 0, 255, 1)">__CLASS__</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> C <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> A
{
}
</span><span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> B();
</span><span style="color: rgba(128, 0, 128, 1)">$b</span>->test();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">A ($this->who()) B (static::who())</span>
<span style="color: rgba(128, 0, 128, 1)">$c</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> C();
</span><span style="color: rgba(128, 0, 128, 1)">$c</span>->test();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">AA</span></pre>
</div>
<p>多重转发,绑定规则:</p>
<p>后期静态绑定的解析会一<span style="color: rgba(204, 153, 255, 1)">直到取得一个完全解析了的静态调用为止</span>。另一方面,如果静态调用使用 <em>parent::</em> 或者 <em>self::</em> 将转发调用信息</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> who() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(255, 0, 255, 1)">__CLASS__</span>."\n"<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> foo() {
</span><span style="color: rgba(0, 0, 255, 1)">static</span>::<span style="color: rgba(0, 0, 0, 1)">who();
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> B <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> A
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> test() {
A</span>::foo();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">A</span>
parent::foo();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">C</span>
self::foo();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">C</span>
<span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> who ()
{
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(255, 0, 255, 1)">__CLASS__</span>."\n"<span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(0, 0, 255, 1)">class</span> C <span style="color: rgba(0, 0, 255, 1)">extends</span><span style="color: rgba(0, 0, 0, 1)"> B
{
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> who() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(255, 0, 255, 1)">__CLASS__</span>."\n"<span style="color: rgba(0, 0, 0, 1)">;
}
}
C</span>::test();<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">A C C</span></pre>
</div>
<p> 对象和引用</p>
<p>在php5 的对象编程经常提到的一个关键点是“默认情况下对象是通过引用传递的”。但其实这不是完全正确的。</p>
<p>PHP 的引用是别名,就是两个不同的变量名字指向相同的内容。在 PHP 5,<span style="color: rgba(204, 153, 255, 1)">一个对象变量已经不再保存整个对象的值。只是保存一个标识符来访问真正的对象内容</span>。 当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,<span style="color: rgba(204, 153, 255, 1)">只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容</span></p>
<p> </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$foo</span> = 1<span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(128, 0, 128, 1)">$a</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> $a ,$b都是同一个标识符的拷贝
// ($a) = ($b) = <id></span>
<span style="color: rgba(128, 0, 128, 1)">$b</span>->foo = 2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$a</span>->foo."\n";<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2</span>
<span style="color: rgba(128, 0, 128, 1)">$b</span> = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$a</span>->foo."\n";<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2</span>
<span style="color: rgba(128, 0, 128, 1)">$c</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(128, 0, 128, 1)">$d</span> = &<span style="color: rgba(128, 0, 128, 1)">$c</span>; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> $c ,$d是引用
// ($c,$d) = <id></span>
<span style="color: rgba(128, 0, 128, 1)">$d</span>->foo = 2<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$c</span>->foo."\n";<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2</span>
<span style="color: rgba(128, 0, 128, 1)">$d</span> = <span style="color: rgba(0, 0, 255, 1)">null</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">$c也为null 此时应用unset</span>
<span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$c</span>->foo."\n";<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">Trying to get property 'foo' of non-object </span>
<span style="color: rgba(128, 0, 128, 1)">$e</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(0, 0, 255, 1)">function</span> foo(<span style="color: rgba(128, 0, 128, 1)">$obj</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ($obj) = ($e) = <id></span>
<span style="color: rgba(128, 0, 128, 1)">$obj</span>->foo = 2<span style="color: rgba(0, 0, 0, 1)">;
}
foo(</span><span style="color: rgba(128, 0, 128, 1)">$e</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$e</span>->foo."\n";<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">2</span></pre>
</div>
<p>对象的序列化</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> classa.inc:</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> A {
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(128, 0, 128, 1)">$one</span> = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> show_one() {
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> <span style="color: rgba(128, 0, 128, 1)">$this</span>-><span style="color: rgba(0, 0, 0, 1)">one;
}
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> page1.php:</span>
<span style="color: rgba(0, 0, 255, 1)">include</span>("classa.inc"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> A;
</span><span style="color: rgba(128, 0, 128, 1)">$s</span> = <span style="color: rgba(0, 128, 128, 1)">serialize</span>(<span style="color: rgba(128, 0, 128, 1)">$a</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 把变量$s保存起来以便文件page2.php能够读到</span>
<span style="color: rgba(0, 128, 128, 1)">file_put_contents</span>('store', <span style="color: rgba(128, 0, 128, 1)">$s</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> page2.php:
// 要正确了解序列化,必须包含下面一个文件</span>
<span style="color: rgba(0, 0, 255, 1)">include</span>("classa.inc"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$s</span> = <span style="color: rgba(0, 128, 128, 1)">file_get_contents</span>('store'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$a</span> = <span style="color: rgba(0, 128, 128, 1)">unserialize</span>(<span style="color: rgba(128, 0, 128, 1)">$s</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 现在可以使用对象$a里面的函数 show_one()</span>
<span style="color: rgba(128, 0, 128, 1)">$a</span>->show_one();</pre>
</div>
<p>用于传递实例从一个页面到另一个页面</p>
<p>当一个应用程序使用函数<span class="function">session_register()来保存对象到会话中时,在每个页面结束的时候这些对象都会自动序列化,而在每个页面开始的时候又自动解序列化。 所以一旦对象被保存在会话中,整个应用程序的页面都能使用这些对象。但是,<span class="function">session_register()在php5.4.0之后被移除了</span></span></p>
<p><span class="function">当反序列化之后,如果此类没有定义,还是不能用的</span></p>
<p><span class="function">反射</span></p>
<p><span class="function">PHP 5 具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行<em>反向工程</em>的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释</span></p><br><br>
来源:https://www.cnblogs.com/ValleyUp/p/11181141.html
頁:
[1]