介紹PHP面向對象的基礎知識
1. 接口的定義interface ,類定義class,類支持abstract和final修飾符,abstract修飾為抽象類,抽象類
不支持直接實例化,final修飾的類/方法不能被繼承/方法重寫.
2. 接口的實現通過implements,類繼承extends
interface IShape{ function draw_core(); }; class PathShape implements IShape{ public function draw_core(){} } class Rectangle extends PathShape{ public function draw_core(){ //overide draw_core } }
3.靜態變量和常量(static ,const )
a.常量聲明變量名前面不需要加美元修飾符$,靜態變量需要
b.兩者都通過類訪問,靜態變量方法時候需要在變量名前加$美元修飾符好
class MyClass{ const M_CONST_VALUE; static $M_STATIC_VALUE; } MyClass::M_CONST_VALUE ; MyClass::$M_STATIC_VALUE;
c.常量聲明時候不支持訪問權限修飾符,不能在const前加public,常量默認就是public。
const M_CONST ; //OK public const M_CONST ; // throw exception
4.類內部訪問非靜態/常量變量和方法通過$this,訪問父類通過parent,在類內部訪問靜態變量和方法可以通過
self,self本質是指向該類也可以通過static訪問
parent::method(); //父類方法 $this->method() ; //方法實例方法 self::$static_value ;//訪問靜態變量 static::$static_value;//同上
5.static和self的區別在於self指的是解析上下文,也是是作用與當前類,static指的是被調用
的類而不是包含類,典型的例子就是單例
abstract class ParentClass{ public static function createInstance(){ return new static(); //這裡不能使用self,因為self本意其實指向parentclass的 //如果你使用了self,那麼將拋出異常,提示抽象類無法實例化 //而static並不直接指向parentclass而是作用與包含類 // } } class ChildClass extends ParentClass{ // }
7.類中使用攔截器,PHP攔截器有__get,__set,__inset,__unset,__call,這裡只關注geth和set攔截器
__get($property) 當訪問未定義的屬性時候該方法被調用 __set($property,$value)當給未定義的屬性賦值時被調用 class MyClass{ public function __get($property){ echo "Access __get"; if(property_exists($this,$property)){ return $this->$property; }else{ return "unknown"; } } public function __set($property,$value){ if(!property_exists($this,$property)){ $this->Name = $value; //變量不存在就直接給$Name賦值 } } public $Name = "visonme"; }; //訪問 $obj = new MyClass(); $obj->Name ; //直接訪問變量$Name $obj->Password;//Password未定義,先訪問__get最後輸出unknown //-for __set $obj->password = 'fz-visonme';//password不存在,那麼將走__setz最後給$Name賦值 echo $obj->Name ; // output: fz-visonme
8.類構造函數和析構函數:__construct, __destruct ,構造函數實例化對象時候調用,多用於成員變量初始化工作,析構在類銷毀時候調用,多用於收尾工作
class MyClass{ function __construct(){} function __destruct(){} }
9.對象的復制通過clone,clone關鍵字使用“值復制"方式來產生一個新的對象,對於對象復制本身還是走引用復制的。
a.簡單類型賦值
class MyClass{ public $ID; }; $a = new MyClass; $a->ID = 199; $b = clone $a; echo $b->ID; // output: 199
b.包含對象的復制
class Account{ public $RMB; }; class MyClass{ public $ID; public $AccountObj; public function __construct($c){ $this->AccountObj = $c; } }; $a = new MyClass(new Account()); $a->AccountObj->RMB= 199; $b = clone $a; echo $b->AccountObj->RMB; //output: 199 $a->AccountObj->RMB = 100; echo $b->AccountObj->RMB; //output: 100 在clone後,$a的AccountObj改變時候,同時會影響到$b
這種結果顯然不是我們所期望的,我們所期望的是ab是兩個不存在任何關聯的獨立對象.
為了解決這個問題我麼可以在類內部實現__clone,當我們在外面調用clone時候其內部會調用類的__clonef方法,所以我們可以通過重寫__clone來達到對clone的控制.例如針對b例子的改造
class MyClass{ public $ID; public $AccountObj; public function __construct($c){ $this->AccountObj = $c; } //__clone實現clone的控制 //這裡內部同時對Account實現一次clone,這裡就可以避免b例子中出現的問題 public function __clone(){ $this->ID = 0 ; //將ID置為0,如果你需要的話 $this->AccountObj = clone $this->AccountObj; } };
關於__clone方法我們需要知道,該方法是在被clone後的對象上調用,而不是在原始的對象上面運行的,例如上b例子中
$b = clone $a ; //執行的過程: 基本復制對象$a ---> $b執行__clone()