2010年最新PHP類的精髓歸納第2/2頁
十:類型提示:
注意,類型提示功能只能用于參數(shù)為對象的提示,而無法用于為整數(shù),字串,浮點(diǎn)等類型提示。有些類的方法需要傳入的參數(shù)為所期望的對象類型,可以用下面的方法達(dá)到強(qiáng)制實(shí)施此替則。要達(dá)到類型提示,只要在方法的對象型參數(shù)前加一個已存在的類的名稱,如:function funname(OtherClassName $otherclassINSName,$c....),注意,OtherClassName必須是存在的類。如下:
class em{ var $k=56; }
class test{
function __construct()
{ echo $this->addab(new em(),2); }
function addab(em $j,$c) //這個方法,即可以在內(nèi)部調(diào)用,也可以在外部調(diào)用。只要作用域許可。
{ return $j->k+$c; }
}
$a = new test();
$b = new em();
echo $a->addab($b,2); //或 $a->addab(new em(),2);
十一、類的管理:
1、instanceof關(guān)鍵字:用于分析一個對象是否是某一個類的實(shí)例或子類或是實(shí)現(xiàn)了某個特定的接口:如下例,但要注意: 類名沒有任何引號等定界符,否則會出錯。如test不能用'test'
class test2{}
class test{}
class testChilern Extends test{}
$a = new test2();
$m = new test();
$i = ($m instanceof test);
if($i)echo '$m是類test的實(shí)例!<br />'; // get this value
switch ($a instanceof test){
case true :
echo 'YES<br />';
break;
case false :
echo 'No<br />'; //get this value
break;
}
$d=new testChilern();
if($d instanceof test)echo '$d是類test的子類!<br />'; // get this value
2、確定類是否存在:boolean class_exists(string class_name): class_exists('test');
3、返回類名:string get_class(object),成功時返回實(shí)例的類名,失敗則返回FALSE:
$a = new test2(); echo get_class($a); //返回 test2
4、了解類的公用屬性:array get_class_vars('className') ,返回關(guān)鍵數(shù)組:包含所有定義的public屬性名及其相應(yīng)的值。這個函數(shù)不能用實(shí)例名做變量
5、返回類方法:get_class_methods('test'); //或: get_class_methods($a);可用實(shí)例名做參數(shù),返回包括構(gòu)造函數(shù)在內(nèi)的所有非私有方法。
6、print_r(get_declared_classes())了解當(dāng)前PHP版本中所有的類名。PHP5有149個。
7、get_object_vars($a)返回實(shí)例中所有公用的屬性及其值的關(guān)聯(lián)數(shù)組。注意它和get_class_vars()的區(qū)別:
/* (1) get_object_vars($a)是用實(shí)例名做參數(shù),而get_class_vars('test')是用類名做參數(shù)。
* (2) get_object_vars($a)獲得的屬性值是實(shí)例運(yùn)行后的值,而get_class_vars('test')獲得的屬性值是類中的初始定義。
* (3) 兩者均返回關(guān)聯(lián)數(shù)組,且均對未賦值的屬性返回NULL的值。如類test中有定義了public $q;則返回Array ( [v] => 5 [q]=>) ,
*/
8、返回父類的名稱:get_parent_class($b);//或get_parent_class('test2'); 返回test
9、確定接口是否存在:boolean interface_exists($string interface[,boolean autoload])
10、確定對象類型: boolean is_a($obj,'className'),當(dāng)$obj屬于CLASSNAME類時,或?qū)儆谄渥宇悤r,返回TRUE,如果$obj與class類型無關(guān)則返回FALSE。如:is_a($a,'test')
11、確定是否是某類的子對象:當(dāng)$b是繼承自TEST類時,返回TRUE,否則FALSE。boolean is_subclass_of($b,'test');
12、確定類或?qū)嵗?,是否存在某方法。method_exists($a,'getv') //或用method_exists('test','getv'),此函數(shù)適用于非public定義的作用域的方法。
以上函數(shù)實(shí)例:
class test{
public $v=2;
private $c=5;
function __construct(){
$this->v=5;
}
private function getv(){
return $this->v;
}
}
class test2 extends test{}
$a=new test();
$b=new test2();
print_r( get_class_methods('test')); //或:print_r( get_class_methods($a)); 均返回:Array ( [0] => __construct [1] => getv )
echo '<br />';
print_r( get_class_vars('test')); //返回:Array ( [v] => 2 ),和上面不一樣,不能用print_r( get_class_methods($a));
echo '<br />';
echo get_parent_class($b);//或get_parent_class('test2'); 返回test
echo '<br />';
echo is_a($b,'test');// 返回1
echo '<br />';
if(is_subclass_of('test2','test'))echo '是子類!'; //或(is_subclass_of($b,'test')),返回1,當(dāng)參數(shù)1為$a時則返回false,
echo '<br />';
echo method_exists($a,'getv') //或用method_exists('test','getv')返回1,本函數(shù)也適用于用private等定義域的方法。
十一、自動加載類庫文件:
當(dāng)類多了以后,比如要在一個文件中載入3個類庫文件:a.class.php,b.class.php,c.class.php要用三個require_once('classes/a.class.php);
require_once('classes/b.class.php);
require_once('classes/c.class.php);
可以用PHP5自動加載的功能來處理:在全局應(yīng)用配置文件中,定義一個特殊的函數(shù)__autoload($class)函數(shù)(__autoload并不是一個類的方法,只是單獨(dú)的函數(shù),和類沒有關(guān)系):
function __autoload($class){
require_once("classes/$class)
}
該函數(shù)放哪沒有關(guān)系,在創(chuàng)建類實(shí)例時,也不必去調(diào)用這個autoload函數(shù)。PHP會自動完成。但務(wù)必注意一點(diǎn):“在調(diào)用頁面上創(chuàng)建實(shí)例所使用的類名稱”、和“被調(diào)用的文件名”、以及“該文件中的類的名稱”3個必須是一樣的。這樣就不需要去調(diào)用__autoload();如果不一樣則必須單獨(dú)調(diào)用__autoload('c');并給它一個文件名前綴。如:
c.class.php文件的代碼是:
<?php
class c{
public $m=7;
}
?>這里代碼的類名稱是c,而文件名也是c,
現(xiàn)在要在index.php調(diào)用:
<?php
function __autoload($class){
require_once "$class.class.php";
}
$m = new c(); //創(chuàng)建實(shí)例調(diào)用的類也是c
echo $m->m;
?>
此時PHP會自動調(diào)用根目錄下的c.class.php中的類C。
但如果c.class.php中的代碼是:
<?php
class mm{
public $m=7;
}
?>
而調(diào)用頁index.php代碼是:
<?php
function __autoload($class){
require_once "$class.class.php";
}
# __autoload('c'); //如果不加這一行就會出錯。
$m = new mm();
echo $m->m;
?>
會出錯,提示找不到mm.class.php文件。這時可以加一行__autoload('c');但這樣就達(dá)不到簡化代碼的目的。
類的家族化擴(kuò)展:類的高級功能:
一、對象克隆:
當(dāng)克隆一個對象的實(shí)例時,其屬性初始值繼承了被克隆對象的當(dāng)前值。
class test
{
public $p=5;
function __clone(){ //只在克隆發(fā)生時起作用。用于改變在克隆時某些值
$this->p=15;
}
}
$a=new test();
echo $a->p;
$a->p=8; //如果沒有__clone()方法影響,$b的P值將為8
$b = clone $a;
echo $b->p; //15
二、對象繼承:
沒有被聲明為final的類可以被繼承,沒有被final和private界定的方法也可以繼承,沒有被private界定的屬性也可以繼承。當(dāng)子類繼承了父類或超類后,可以直接使用父類或超類(祖父類以及祖父的祖父)的所有允許的方法,屬性。
關(guān)鍵:理解構(gòu)造函數(shù)和重載在繼承中的特性!
(一)構(gòu)造函數(shù)在繼承中的特性:
1、當(dāng)父類有構(gòu)造函數(shù)而子類沒有:則子類會在實(shí)例化時會自動執(zhí)行父類的構(gòu)造函數(shù)。這時如果要創(chuàng)建子類的實(shí)例,需要引入父類構(gòu)造函數(shù)中所需的參數(shù),否則出錯。即使是“子類的子類”如果沒有構(gòu)造函數(shù),也要在創(chuàng)建實(shí)例時輸入其父類的父類的構(gòu)造函數(shù)所需參數(shù)。PHP會從實(shí)例所在的子類會向上搜索合造的構(gòu)造函數(shù),一旦找到就停止,使用該構(gòu)造函數(shù)。而不會再向上搜索,因此:子類本身如果沒有構(gòu)造函數(shù),則以其最靠近的一個超類并且有構(gòu)造函數(shù)的為準(zhǔn)。
class cA{
public $name,$age;
function __construct($n) {
$this->name = $n;
$this->age = 25;
}
function __set($n,$v) {
$this->$n = $v;
}
function __get($n) {
return $this->$n;
}
}
class cB extends cA{
function funB1() { echo '<h3>Class cB execute success!</h3>'; }
}
class cC extends cB {
function funC1() { echo '<h3>Class cC FunC1!</h3>'; }
}
$b=new cB('Jack');
$b->name='John';
echo "$b->name : $b->age";
$b->funB1();
$c=new cC(); //這里會出錯,由于cB也沒有構(gòu)造函數(shù),因此再向上以cA為準(zhǔn),需要一個參數(shù)。改為$c=new cC('David');即可。
echo $c->name(); //David
2、當(dāng)子類也有構(gòu)造函數(shù)時:這時,不管父類是否有構(gòu)造函數(shù),都會執(zhí)行子類自己的構(gòu)造函數(shù)。
如上:
class cB extends cA{
function __construct() {
echo '<h3>this is Class cB \'s __construct!</h3>';
}
function funB1() {
echo '<h3>Class cB execute success!</h3>';
}
}
現(xiàn)在類CB有自己的構(gòu)造函數(shù)時,這時創(chuàng)建實(shí)例$b=new cB('Jack');參數(shù)JACK不會起作用,因?yàn)楦割怌A的構(gòu)造函數(shù)沒有得到執(zhí)行。因此$b->name和$->age就不會初始化值。需要另外賦值$b->name='Jack',$b->age=25;
如果這時要執(zhí)行父類CA的構(gòu)造函數(shù),可以這樣:
function __construct($n) {
parent::__construct($n); // 或:cA::__construct($n);
echo '<h3>this is Class cB \'s __construct!</h3>';
}
由于parent::__construct($n); 只會向上搜索父類的構(gòu)造函數(shù),一找到就停止且執(zhí)行當(dāng)前找到的構(gòu)造函數(shù),因此在上面例子中,如果parent::__construct($n)是用在最后一層的類cC中,并且類CB,CA都有構(gòu)造函數(shù),那么cC的實(shí)例只會執(zhí)行cB的構(gòu)造函數(shù)。不會執(zhí)行cA。這時,如果CC的實(shí)例想都調(diào)用CA和CB的構(gòu)造函數(shù),有兩種方法:
A、在CB中也加入parent::__construct($n)
B、在CC中把構(gòu)造函數(shù)改為:
function __construct($n) {
cA::__construct($n); //即:類名::構(gòu)造函數(shù)。
cB::__construct();
echo '<h3>this is Class cB \'s __construct!</h3>';
}
(二)在子類中調(diào)用父類的屬性或方法:
1、調(diào)用父類方法:在子類中調(diào)用父類的方法,有3種方法:
$this->ParentFunction(); 或
父類名::ParentFunction(); 或
parent::parentFun();
2、調(diào)用父類屬性:只能用$this->ParentProperty;
(三)重載:
在子類中,可以定義與父類相同屬性或方法,改變父類該屬性或方法的值或操作,稱做重載。如:
calss ParClass{ function pfun(){ ....}}
class ChildrenClass extends ParClass{function pfun(){ ....}}} //重載了父類的pfun的方法。
在子類中重載后,優(yōu)先執(zhí)行自己重載后的新定義的方法或?qū)傩浴?BR>也可以在子類中用parent::parentFun();調(diào)用父類的方法,但所得到的值是子類自己輸入的參數(shù)運(yùn)算值。而不是該方法在父類中運(yùn)算的值。
三、接口:
接口:interface,可以理解成一組功能的共同規(guī)范,最大意義可能就是在多人協(xié)作時,為各自的開發(fā)規(guī)定一個共同的方法名稱。
和抽象類中的抽象方法一樣:
1、不能在接口中對方法具體實(shí)現(xiàn)進(jìn)行定義。而是由具體類來實(shí)現(xiàn)(而抽象類中的非抽象方法可以不必再定義,只有抽象方法和接口是一樣要求要在具體類中實(shí)現(xiàn))。
2、和抽象類一樣,可以在接口中定義常量,并由具體類直接繼承。
3、具體類必須實(shí)現(xiàn)抽象類的所有抽象方法(非抽象方法除外),同樣,具體類如通過implements實(shí)現(xiàn)了接口后,必須完成接口中的所有方法。
接口實(shí)現(xiàn)過程:1、定義接口,2、用..implement X,Y,...和具體類對接。
interface Info{ //定義接口
const N=22;
public function getage();
public function getname();
}
class age implements Info //如要多個接口 class age (extends emJob) implements Info,interB...
{
public $age=15;
public $name='Join';
function getage() {
echo "年級是$this->age";
}
function getname() {
echo "姓名是$this->name";
}
function getN(){
echo '<h3>在接口中定義的常量N的值是:'.$this::N.' </h3>'; //直接繼承接口中的常量值。
}
}
$age=new age;
echo $age::N; //22,直接調(diào)用接口中的常量值。
$age->getN();
關(guān)于抽象類和接口類的使用區(qū)分:何時用接口,何時用抽象?
1、相關(guān)性:當(dāng)創(chuàng)建的模型由一些緊密相關(guān)的對象采用時,用抽象。對于不相關(guān)對象采用的功能,用接口。
2、多重繼承:PHP類可以繼承多個接口,但不能擴(kuò)展多個抽象類。
3、公共行為實(shí)現(xiàn):抽象類可在其中實(shí)現(xiàn)公共的方法,但接口不行。
四、命名空間(PHP6)
類庫腳本A.inc.php和腳本B.inc.php中都一個類的名稱為 class CNAME,并且這兩個文件要在同一個文件如index.php中被調(diào)用。這時要用到命名空間。
步聚:
1、打開上面的A和B兩個文件,分別在上面的最前面各加一行:
namespace SPACEA; 和 namespace SPACEB; 名字自定。
2、在index.php中實(shí)例化類時,在類的前面添加命名空間和雙冒號做為前綴:
include 'a.inc.php';
include 'b.inc.php';
$a=new SPACEA::CNAME();
$b=new SPACEB::CNAME();
這樣就不會沖突了。
但在PHP6正式發(fā)布前,這個功能還未定下來。
五、實(shí)現(xiàn)迭代器和迭代。
參《PHP圣經(jīng)》P142;
六、使用Reflection(反射)API 。
簡易實(shí)例:
class a{ .... }
$c = new ReflectionClass('a'); //PHP 內(nèi)置類。
echo '<pre>'.$c.'</pre>';
輸出類a的結(jié)構(gòu)和內(nèi)容。參《PHP圣經(jīng)》P145;
相關(guān)文章
高并發(fā)php uniqid不重復(fù)唯一標(biāo)識符生成方案
這篇文章主要介紹了高并發(fā)php uniqid不重復(fù)唯一標(biāo)識符生成方案,對高并發(fā)感興趣的同學(xué),一定要看一下2021-04-04解析php做推送服務(wù)端實(shí)現(xiàn)ios消息推送
本篇文章是對php做推送服務(wù)端實(shí)現(xiàn)ios消息推送的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-07-07php模塊memcache和memcached區(qū)別分析
談及php搭配memcached使用,已經(jīng)是老生常談的問題。但是有一些細(xì)節(jié),不見得人人清楚。比如說php的模塊memcache和memcached有什么區(qū)別等。下面我就簡單介紹一下。2011-06-06PHP判斷IP并轉(zhuǎn)跳到相應(yīng)城市分站的方法
這篇文章主要介紹了PHP判斷IP并轉(zhuǎn)跳到相應(yīng)城市分站的方法,實(shí)例分析了php解析URL及跳轉(zhuǎn)的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03Windows服務(wù)器中PHP如何安裝redis擴(kuò)展
一句話總結(jié):下載擴(kuò)展的dll,放入指定文件夾(php對應(yīng)的擴(kuò)展的目錄php/ext),在配置文件php.ini中注冊dll,這里就為大家分享一下2019-09-09