PHP中的类
用php以來(lái),一直懷念java的類和對(duì)象,終于PHP 5 引入了新的對(duì)象模型(Object Model)。完全重寫了 PHP 處理對(duì)象的方式,向java靠齊了。下面來(lái)了解下吧!
?
一、定義類和實(shí)例化對(duì)象
php以關(guān)鍵字class來(lái)定義類,使用new來(lái)創(chuàng)建一個(gè)對(duì)象的實(shí)例,這就不用多說(shuō)了。
?
二、自動(dòng)加載對(duì)象機(jī)制
以前,我們引用對(duì)象,都要在前面使用include或者require將類包含進(jìn)來(lái),有時(shí)一個(gè)頁(yè)面引用的類多了,感覺(jué)很麻煩,php5種,不再需要這樣了,我們可以定義一個(gè)__autoload函數(shù),它會(huì)在試圖使用尚未被定義的類時(shí)自動(dòng)調(diào)用。這就省得我們?cè)诿總€(gè)頁(yè)面都要使用一堆的包含函數(shù)了。
?
使用實(shí)例:
類文件:/class/class.testOne.php
<?phpclass testOne{function __construct(){echo "begin";}function __destruct() {}}?>類文件:/class/class.testTwo.php
<?phpclass testTwo{protected $name;function __construct(){echo "conn";}function setName( $name ){$this->name = $name;}function getName(){return "My name is:".$this->name;}function __destruct() {}}?>?
文件:/comm.config.php
<?phpfunction __autoload( $class_name) {require_once "./class/class.".$class_name.'.php';}?>?
文件:/index.php
<?phprequire_once( "comm.config.php" );$testOne = new testOne();?>輸出結(jié)果:begin
?
文件:/index2.php
<?phprequire_once( "comm.config.php" );$testTwo = new testTwo();$testTwo->setName( "test" );echo $testTwo->getName();?>輸出結(jié)果:connMy name is:test
?
?
三、構(gòu)造函數(shù)和析構(gòu)函數(shù)
構(gòu)造函數(shù):void __construct ( [mixed args [, ...]] )
具有構(gòu)造函數(shù)的類會(huì)在每次創(chuàng)建對(duì)象時(shí)先調(diào)用此方法,我們可以在這里做一些初始化操作。
?
析構(gòu)函數(shù):void __destruct ( void )
PHP 5 引入了析構(gòu)函數(shù)的概念,這類似于其它面向?qū)ο蟮恼Z(yǔ)言,如 C++。析構(gòu)函數(shù)會(huì)在到某個(gè)對(duì)象的所有引用都被刪除或者當(dāng)對(duì)象被顯式銷毀時(shí)執(zhí)行。
?
注意:
在繼承父類的子類中,默認(rèn)子類是不會(huì)實(shí)現(xiàn)父類的構(gòu)造函數(shù)和析構(gòu)函數(shù),要執(zhí)行父類的構(gòu)造函數(shù)和析構(gòu)函數(shù),我們可以使用parent關(guān)鍵字在子類的構(gòu)造函數(shù)和析構(gòu)函數(shù)體中顯式調(diào)用parent::__construct()和parent::__destruct()。
?
四、屬性和方法的可見(jiàn)性
在php5中,我們可以像java一樣,使用public、private、protected關(guān)鍵字來(lái)定義屬性或者方法的可見(jiàn)性范圍。
public:聲明方法和屬性可以被隨意訪問(wèn)。
Protected:聲明的方法和屬性只能被類本身和其繼承子類訪問(wèn)。
private:只能被定義屬性和方法的類訪問(wèn)。
?
?
實(shí)例:
文件:class.testOne.php
<?phpclass testOne{public $public = "testOne.public";protected $protected = "testOne.preteced";private $private = "testOne.private";function __construct(){}public function getPublic(){return "From testOne.getPublic:".$this->public;}//endprotected function ?getProtected(){return "From testOne.getProtected:".$this->protected;}private function getPrivate(){return "From testOne.getPrivate:".$this->private;}function printAll(){echo $this->public.BR;echo $this->getPublic().BR;echo $this->protected.BR;echo $this->getProtected().BR;echo $this->private.BR;echo $this->getPrivate().BR;}function __destruct() {}}?>?
文件:index.php
<?phprequire_once( "class.testOne.php" );$testOne = new testOne();### ? ?屬性echo $testOne->public.BR;echo $testOne->protected.BR; ? ? //Fatal error: Cannot access protected property testOne::$protected in E:\www3\test\index.php on line 6echo $testOne->private.BR; ? ?//Fatal error: Cannot access private property testOne::$private in E:\www3\test\index.php on line 7### ? ?方法echo $testOne->getPublic().BR;echo $testOne->getProtected().BR;//Fatal error: Call to protected method testOne::getProtected() from context '' in E:\www3\test\index.php on line 10echo $testOne->getPrivate().BR;//Fatal error: Call to private method testOne::getPrivate() from context '' in E:\www3\test\index.php on line 11### ? ?內(nèi)部訪問(wèn)$testOne->printAll();echo "-----------------".BR;### ? ?定義擴(kuò)展類class SunClass extends testOne{protected $protected = 'SunClass.protected';function printAll(){echo $this->public.BR;echo $this->getPublic().BR;echo $this->protected.BR;echo $this->getProtected().BR;echo $this->private.BR;//這里不報(bào)錯(cuò),但是值是空的echo $this->getPrivate().BR;//Fatal error: Call to private method testOne::getPrivate() from context 'SunClass' in E:\www3\test\index.php on line 25}}### ? ?子類訪問(wèn)$obj2 = new SunClass();$obj2->printAll();?>正常無(wú)錯(cuò)誤的輸出如下:testOne.publicFrom testOne.getPublic:testOne.publictestOne.publicFrom testOne.getPublic:testOne.publictestOne.pretecedFrom testOne.getProtected:testOne.pretecedtestOne.privateFrom testOne.getPrivate:testOne.private-----------------testOne.publicFrom testOne.getPublic:testOne.publicSunClass.protectedFrom testOne.getProtected:SunClass.protected以上實(shí)例說(shuō)名:public或者默認(rèn)無(wú)聲明的屬性和方法無(wú)論怎么樣都可以被訪問(wèn)到。protected的屬性和方法只能在類內(nèi)部或者繼承子類內(nèi)部訪問(wèn)。private的屬性和方法只能在類自身內(nèi)部訪問(wèn)。?
?
五、static關(guān)鍵字
將一個(gè)類的屬性或者方法定義為static,則可以在不實(shí)例化類的情況下使用類的屬性和方法。
?
注意:
1、static關(guān)鍵字必須在public、protected、private之后聲明。
2、子類不能重新定義父類中static關(guān)鍵字修飾的變量屬性或者方法,除非你將它們定義為static成員。
3、static方法或者變量中,$this 變量是不可用的,如果你要使用同一類中其他的定義為static變量或者方法,可以使用self::(變量名|方法名)來(lái)訪問(wèn)static成員。
4、Static成員屬性不能以$object->(static成員屬性)方式訪問(wèn),你可以$類名::(static成員屬性)訪問(wèn)它們。這里跟java不同,PHP中static成員是不能被類的實(shí)例對(duì)象訪問(wèn)的。
?
實(shí)例:
<?phprequire_once( "comm.config.php" );class Foo{public static $my_static = 'foo';public function staticValue() {###echo $this->$my_static; ? ?//(不能使用$this變量訪問(wèn)static成員)Fatal error: Cannot access empty property in E:\www3\test\index.php on line 8return self::$my_static;}}class Bar extends Foo{###public static $my_static;//Fatal error: Cannot redeclare static Foo::$my_static as non static Bar::$my_static in E:\www3\test\index.php on line 20(在public后面加上static關(guān)鍵字就ok了)public function fooStatic() {return self::$my_static;}}$foo = new Foo();print $foo->staticValue() . "\n";print Foo::$my_static . "\n";print $foo->my_static . "\n"; ? ? ?// my_static屬性是空的。echo "<br>";// $foo::my_static is not possibleprint Bar::$my_static. "\n";print Bar::staticValue(). "\n";$bar = new Bar();print $bar->fooStatic() . "\n";?>正確的輸出結(jié)果:
foo foo
foo foo foo
?
?
六、作用域分辨運(yùn)算符(::)
在沒(méi)有聲明任何實(shí)例的情況下使用::來(lái)訪問(wèn)類中的函數(shù)或者基類中的函數(shù)和變量。
一般用在以下三種情況
1、從類外部不經(jīng)過(guò)實(shí)例化訪問(wèn)類成員(比如static或者常量),
使用格式:類名::成名名;
2、類內(nèi)部使用,通過(guò)關(guān)鍵字self和parent來(lái)實(shí)現(xiàn)類內(nèi)部訪問(wèn)類定義的成員.
3、子類通過(guò)關(guān)鍵字parent來(lái)訪問(wèn)父類成員。
?
實(shí)例:
class FatherClass{const CONST_VALUE = 'FatherClass.const';static $static = "FatherClass.static";private function goPrivate(){echo "FatherClass.goPrivate<br>";}protected function goProtected() {echo "FatherClass.goProtected<br>";}function goPublic() {echo "FatherClass.goPublic<br>";self::goPrivate();//self關(guān)鍵字訪問(wèn)內(nèi)部私有方法self::goProtected();//self關(guān)鍵字訪問(wèn)內(nèi)部保護(hù)方法echo self::CONST_VALUE."<br>";//self訪問(wèn)類內(nèi)部常量echo self::$static."<br>";//self訪問(wèn)類內(nèi)部static變量}}class SunClass extends FatherClass{function goPrivate(){echo "重載父類方法:SunClass.goPrivate<br>";###parent::goPrivate();//Fatal errorparent::goProtected(); ? ?//parent訪問(wèn)父類protected方法echo parent::CONST_VALUE."<br>";//parent訪問(wèn)父類常量echo parent::$static."<br>";//parent訪問(wèn)父類static變量}}###FatherClass::goPrivate();//這里會(huì)出現(xiàn)Fatal error:,因?yàn)閜rivate修飾的成員外部是不能訪問(wèn)的。
###FatherClass::goProtected();//這里會(huì)出現(xiàn)Fatal error:,因?yàn)閜rotected修飾的成員外部是不能直接訪問(wèn)的,只有子類或者類本身才能訪問(wèn)。
echo FatherClass::CONST_VALUE."<br>";//通過(guò)::訪問(wèn)到類內(nèi)部常量
echo FatherClass::$static."<br>";//訪問(wèn)類的static變量
FatherClass::goPublic();//訪問(wèn)類成員方法
$sunclass = new SunClass();
$sunclass->goPrivate();
?
輸出結(jié)果:
FatherClass.const
FatherClass.static
FatherClass.goPublic
FatherClass.goPrivate
FatherClass.goProtected
FatherClass.const
FatherClass.static
重載父類方法:SunClass.goPrivate
FatherClass.goProtected
FatherClass.const
FatherClass.static
?
七、類常量
我們可以通過(guò)定義類常量使得類的每個(gè)實(shí)例化對(duì)象中,成員的值都是相同的,而且對(duì)象不能改變它的值。
常量和其他變量的區(qū)別主要在于:
1.類的實(shí)例化對(duì)象是不能改變常量的值,并且每個(gè)實(shí)例化對(duì)象的常量值都是相同的。
2.不需要$符號(hào)來(lái)聲明和使用常量。
3.常量不能被類的實(shí)例化對(duì)象直接使用,它只能在類內(nèi)部使用。這點(diǎn)跟static成員是一相同的。
?
實(shí)例:
class MyClass{const constant = 'constant value';function showConstant() {//self::constant = "change constant value"; ###會(huì)出現(xiàn)錯(cuò)誤echo ?self::constant . "\n";}}echo MyClass::constant . "\n";$class = new MyClass();$class->showConstant();//echo $class::constant; ?###is not allowed?
?
八、抽象類
PHP5中引入了abstract類和方法的概念。一個(gè)類被聲明為abstract,則此類是不能被實(shí)例化的。
如果在一個(gè)類內(nèi)部有一個(gè)成員方法被聲明成abstract,則這個(gè)類也必須是抽象類。
而且抽象成員方法只能定義方法的名稱,不能定義方法的實(shí)現(xiàn)細(xì)節(jié),這些方法的實(shí)現(xiàn)細(xì)節(jié)是留待繼承
此抽象類的子類去實(shí)現(xiàn)的。子類繼承抽象類時(shí),除非子類仍然聲明為抽象類,否則就必須實(shí)現(xiàn)抽象類中
所有聲明為abstract的成員方法。注意,子類在是實(shí)現(xiàn)抽象類的抽象成員時(shí),子類成員的可見(jiàn)性必須
和抽象類保持一致或者小于抽象類的成員可見(jiàn)性。
比如:抽象方法定義為protected,則實(shí)現(xiàn)此抽象方法的子類必須聲明為protected或者public,而不能聲明為private。
?
實(shí)例:
//class AbstractClass ###如果去掉abstract關(guān)鍵字將出現(xiàn)錯(cuò)誤
abstract class AbstractClass{// Force Extending class to define this methodabstract protected function getValue();abstract protected function prefixValue($prefix);// Common methodpublic function printOut() {print $this->getValue() . "\n";}}class ConcreteClass1 extends AbstractClass{//private function getValue(){ ###如果聲明為private 會(huì)出現(xiàn)錯(cuò)誤public function getValue() {return "ConcreteClass1";}public function prefixValue($prefix) {return "{$prefix}ConcreteClass1";}}//$class = new AbstractClass();###出現(xiàn)錯(cuò)誤,抽象類不能被實(shí)例化$class1 = new ConcreteClass1;$class1->printOut();echo $class1->prefixValue('FOO_') ."\n";?
九、接口
接口允許你創(chuàng)建一個(gè)只有方法聲明,而無(wú)具體實(shí)現(xiàn)的類對(duì)象.接口是一系列方法的聲明,是一些方法特征的集合,
一個(gè)接口只有方法的特征沒(méi)有方法的實(shí)現(xiàn),因此這些方法可以在不同的地方被不同的類實(shí)現(xiàn),
而這些實(shí)現(xiàn)可以具有不同的行為(函數(shù))。 接口把方法的特征和方法的實(shí)現(xiàn)分割開來(lái)。這種分割體現(xiàn)在接口常常代表一個(gè)角色,
它包裝與該角色相關(guān)的操作和屬性,而實(shí)現(xiàn)這個(gè)接口的類便是扮演這個(gè)角色的演員。一個(gè)角色由不同的演員來(lái)演,而不同的演員之間除了扮演一個(gè)共同的角色之外,
并不要求其它的共同之處。
?
注:
1、接口由interface關(guān)鍵字聲明。
2、接口的所有方法作用域必須是public的。
3、接口只定義方法,沒(méi)有任何有實(shí)際意義的代碼,具體的代碼由實(shí)現(xiàn)這個(gè)接口的類來(lái)完成。
4、實(shí)現(xiàn)類通過(guò)implements來(lái)實(shí)現(xiàn)接口,接口所定義的方法,實(shí)現(xiàn)類必須全部實(shí)現(xiàn)。
5、實(shí)現(xiàn)類可以實(shí)現(xiàn)多個(gè)接口,只需要將接口用逗號(hào)隔開即可。
6、對(duì)象是對(duì)某類的事物的抽象,接口是對(duì)對(duì)象的抽象,接口用來(lái)標(biāo)志類的類別。
7、接口是不能實(shí)例化的。
?
實(shí)例:
// 聲明接口'iFaceOne'interface iFaceOne{public function setVariable($name, $var);public function ? ?getVariable( $name );}// 聲明接口'iFaceTwo'interface iFaceTwo{public function getHtml( $str );}//聲明接口'iFaceTwoSun'繼承iFaceTwo接口,擴(kuò)展setHtml方法interface iFaceTwoSun extends iFaceTwo{public function setHtml();}//類one實(shí)現(xiàn)iFaceOne、iFaceTwo接口class one implements iFaceOne,iFaceTwo{private $test = "";//實(shí)現(xiàn)iFaceOne接口的setVariable方法public function setVariable( $name,$var ){echo "one實(shí)現(xiàn)iFaceOne.setVariable<BR>";$this->$name = $var;}//實(shí)現(xiàn)iFaceOne接口的getVariable方法public function getVariable( $name ){echo "one實(shí)現(xiàn)iFaceOne.getVariable<BR>";return $this->$name;}//實(shí)現(xiàn)iFaceTwo接口的getHtml方法public function getHtml( $str ){echo "one實(shí)現(xiàn)iFaceTwo.getHtml<BR>";return $str;}}//類two實(shí)現(xiàn)iFaceTwo接口class two implements iFaceTwoSun{public function getHtml( $str ){echo "two實(shí)現(xiàn)iFaceTwo.getHtml<BR>";return $str;}public function setHtml(){echo "two實(shí)現(xiàn)iFaceTwoSun.getHtml<BR>";}}class three{function get(iFaceTwo $Obj,$str ){return $Obj->getHtml( $str );}function set( iFaceTwo $Obj ){return $Obj->setHtml();}}$three = new three();$one = new one();$two = new two();//$iFaceOne = new iFaceOne(); ? ?//報(bào)錯(cuò),因?yàn)榻涌谑遣荒鼙粚?shí)例化的$one->setVariable( "test","one" );$rs = $one->getVariable( "test" );echo $rs."<hr>";$rs = $two->getHtml( "two" );echo $rs."<br>";$rs = $two->setHtml();echo "<hr>";$rs = $three->get( $one,"one" );echo $rs."<hr>";$rs = $three->set( $two,"two" );echo $rs."<hr>";//$three->setHTML( $one );//報(bào)錯(cuò)$three->set( $two )?
總結(jié)
- 上一篇: PHP实现图片马赛克效果
- 下一篇: PHP中echo与print和print