PHP中的类
用php以來,一直懷念java的類和對象,終于PHP 5 引入了新的對象模型(Object Model)。完全重寫了 PHP 處理對象的方式,向java靠齊了。下面來了解下吧!
?
一、定義類和實例化對象
php以關鍵字class來定義類,使用new來創建一個對象的實例,這就不用多說了。
?
二、自動加載對象機制
以前,我們引用對象,都要在前面使用include或者require將類包含進來,有時一個頁面引用的類多了,感覺很麻煩,php5種,不再需要這樣了,我們可以定義一個__autoload函數,它會在試圖使用尚未被定義的類時自動調用。這就省得我們在每個頁面都要使用一堆的包含函數了。
?
使用實例:
類文件:/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();?>輸出結果:begin
?
文件:/index2.php
<?phprequire_once( "comm.config.php" );$testTwo = new testTwo();$testTwo->setName( "test" );echo $testTwo->getName();?>輸出結果:connMy name is:test
?
?
三、構造函數和析構函數
構造函數:void __construct ( [mixed args [, ...]] )
具有構造函數的類會在每次創建對象時先調用此方法,我們可以在這里做一些初始化操作。
?
析構函數:void __destruct ( void )
PHP 5 引入了析構函數的概念,這類似于其它面向對象的語言,如 C++。析構函數會在到某個對象的所有引用都被刪除或者當對象被顯式銷毀時執行。
?
注意:
在繼承父類的子類中,默認子類是不會實現父類的構造函數和析構函數,要執行父類的構造函數和析構函數,我們可以使用parent關鍵字在子類的構造函數和析構函數體中顯式調用parent::__construct()和parent::__destruct()。
?
四、屬性和方法的可見性
在php5中,我們可以像java一樣,使用public、private、protected關鍵字來定義屬性或者方法的可見性范圍。
public:聲明方法和屬性可以被隨意訪問。
Protected:聲明的方法和屬性只能被類本身和其繼承子類訪問。
private:只能被定義屬性和方法的類訪問。
?
?
實例:
文件: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### ? ?內部訪問$testOne->printAll();echo "-----------------".BR;### ? ?定義擴展類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;//這里不報錯,但是值是空的echo $this->getPrivate().BR;//Fatal error: Call to private method testOne::getPrivate() from context 'SunClass' in E:\www3\test\index.php on line 25}}### ? ?子類訪問$obj2 = new SunClass();$obj2->printAll();?>正常無錯誤的輸出如下: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以上實例說名:public或者默認無聲明的屬性和方法無論怎么樣都可以被訪問到。protected的屬性和方法只能在類內部或者繼承子類內部訪問。private的屬性和方法只能在類自身內部訪問。?
?
五、static關鍵字
將一個類的屬性或者方法定義為static,則可以在不實例化類的情況下使用類的屬性和方法。
?
注意:
1、static關鍵字必須在public、protected、private之后聲明。
2、子類不能重新定義父類中static關鍵字修飾的變量屬性或者方法,除非你將它們定義為static成員。
3、static方法或者變量中,$this 變量是不可用的,如果你要使用同一類中其他的定義為static變量或者方法,可以使用self::(變量名|方法名)來訪問static成員。
4、Static成員屬性不能以$object->(static成員屬性)方式訪問,你可以$類名::(static成員屬性)訪問它們。這里跟java不同,PHP中static成員是不能被類的實例對象訪問的。
?
實例:
<?phprequire_once( "comm.config.php" );class Foo{public static $my_static = 'foo';public function staticValue() {###echo $this->$my_static; ? ?//(不能使用$this變量訪問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關鍵字就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";?>正確的輸出結果:
foo foo
foo foo foo
?
?
六、作用域分辨運算符(::)
在沒有聲明任何實例的情況下使用::來訪問類中的函數或者基類中的函數和變量。
一般用在以下三種情況
1、從類外部不經過實例化訪問類成員(比如static或者常量),
使用格式:類名::成名名;
2、類內部使用,通過關鍵字self和parent來實現類內部訪問類定義的成員.
3、子類通過關鍵字parent來訪問父類成員。
?
實例:
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關鍵字訪問內部私有方法self::goProtected();//self關鍵字訪問內部保護方法echo self::CONST_VALUE."<br>";//self訪問類內部常量echo self::$static."<br>";//self訪問類內部static變量}}class SunClass extends FatherClass{function goPrivate(){echo "重載父類方法:SunClass.goPrivate<br>";###parent::goPrivate();//Fatal errorparent::goProtected(); ? ?//parent訪問父類protected方法echo parent::CONST_VALUE."<br>";//parent訪問父類常量echo parent::$static."<br>";//parent訪問父類static變量}}###FatherClass::goPrivate();//這里會出現Fatal error:,因為private修飾的成員外部是不能訪問的。
###FatherClass::goProtected();//這里會出現Fatal error:,因為protected修飾的成員外部是不能直接訪問的,只有子類或者類本身才能訪問。
echo FatherClass::CONST_VALUE."<br>";//通過::訪問到類內部常量
echo FatherClass::$static."<br>";//訪問類的static變量
FatherClass::goPublic();//訪問類成員方法
$sunclass = new SunClass();
$sunclass->goPrivate();
?
輸出結果:
FatherClass.const
FatherClass.static
FatherClass.goPublic
FatherClass.goPrivate
FatherClass.goProtected
FatherClass.const
FatherClass.static
重載父類方法:SunClass.goPrivate
FatherClass.goProtected
FatherClass.const
FatherClass.static
?
七、類常量
我們可以通過定義類常量使得類的每個實例化對象中,成員的值都是相同的,而且對象不能改變它的值。
常量和其他變量的區別主要在于:
1.類的實例化對象是不能改變常量的值,并且每個實例化對象的常量值都是相同的。
2.不需要$符號來聲明和使用常量。
3.常量不能被類的實例化對象直接使用,它只能在類內部使用。這點跟static成員是一相同的。
?
實例:
class MyClass{const constant = 'constant value';function showConstant() {//self::constant = "change constant value"; ###會出現錯誤echo ?self::constant . "\n";}}echo MyClass::constant . "\n";$class = new MyClass();$class->showConstant();//echo $class::constant; ?###is not allowed?
?
八、抽象類
PHP5中引入了abstract類和方法的概念。一個類被聲明為abstract,則此類是不能被實例化的。
如果在一個類內部有一個成員方法被聲明成abstract,則這個類也必須是抽象類。
而且抽象成員方法只能定義方法的名稱,不能定義方法的實現細節,這些方法的實現細節是留待繼承
此抽象類的子類去實現的。子類繼承抽象類時,除非子類仍然聲明為抽象類,否則就必須實現抽象類中
所有聲明為abstract的成員方法。注意,子類在是實現抽象類的抽象成員時,子類成員的可見性必須
和抽象類保持一致或者小于抽象類的成員可見性。
比如:抽象方法定義為protected,則實現此抽象方法的子類必須聲明為protected或者public,而不能聲明為private。
?
實例:
//class AbstractClass ###如果去掉abstract關鍵字將出現錯誤
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 會出現錯誤public function getValue() {return "ConcreteClass1";}public function prefixValue($prefix) {return "{$prefix}ConcreteClass1";}}//$class = new AbstractClass();###出現錯誤,抽象類不能被實例化$class1 = new ConcreteClass1;$class1->printOut();echo $class1->prefixValue('FOO_') ."\n";?
九、接口
接口允許你創建一個只有方法聲明,而無具體實現的類對象.接口是一系列方法的聲明,是一些方法特征的集合,
一個接口只有方法的特征沒有方法的實現,因此這些方法可以在不同的地方被不同的類實現,
而這些實現可以具有不同的行為(函數)。 接口把方法的特征和方法的實現分割開來。這種分割體現在接口常常代表一個角色,
它包裝與該角色相關的操作和屬性,而實現這個接口的類便是扮演這個角色的演員。一個角色由不同的演員來演,而不同的演員之間除了扮演一個共同的角色之外,
并不要求其它的共同之處。
?
注:
1、接口由interface關鍵字聲明。
2、接口的所有方法作用域必須是public的。
3、接口只定義方法,沒有任何有實際意義的代碼,具體的代碼由實現這個接口的類來完成。
4、實現類通過implements來實現接口,接口所定義的方法,實現類必須全部實現。
5、實現類可以實現多個接口,只需要將接口用逗號隔開即可。
6、對象是對某類的事物的抽象,接口是對對象的抽象,接口用來標志類的類別。
7、接口是不能實例化的。
?
實例:
// 聲明接口'iFaceOne'interface iFaceOne{public function setVariable($name, $var);public function ? ?getVariable( $name );}// 聲明接口'iFaceTwo'interface iFaceTwo{public function getHtml( $str );}//聲明接口'iFaceTwoSun'繼承iFaceTwo接口,擴展setHtml方法interface iFaceTwoSun extends iFaceTwo{public function setHtml();}//類one實現iFaceOne、iFaceTwo接口class one implements iFaceOne,iFaceTwo{private $test = "";//實現iFaceOne接口的setVariable方法public function setVariable( $name,$var ){echo "one實現iFaceOne.setVariable<BR>";$this->$name = $var;}//實現iFaceOne接口的getVariable方法public function getVariable( $name ){echo "one實現iFaceOne.getVariable<BR>";return $this->$name;}//實現iFaceTwo接口的getHtml方法public function getHtml( $str ){echo "one實現iFaceTwo.getHtml<BR>";return $str;}}//類two實現iFaceTwo接口class two implements iFaceTwoSun{public function getHtml( $str ){echo "two實現iFaceTwo.getHtml<BR>";return $str;}public function setHtml(){echo "two實現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(); ? ?//報錯,因為接口是不能被實例化的$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 );//報錯$three->set( $two )?
總結
- 上一篇: PHP实现图片马赛克效果
- 下一篇: 欧曼离合油管是多大的