PHP中的物件導向,PHP物件導向
存取控制(可見度)
PHP的存取控制有 public(公有),protected(受保護)和 private(私人)
被定義為公有的類成員可以在任何地方被訪問。
被定義為受保護的類成員則可以被其自身以及其子類和父類訪問。
被定義為私人的類成員則只能被其定義所在的類訪問。
不能用於修飾class
類屬性不能省略,必須定義為公有,受保護,私人之一。
類中的方法如果沒有設定這些關鍵字,則該方法預設為公有。
同一個類的對象即使不是同一個執行個體也可以互相訪問對方的私人與受保護的成員。這是由於在這些對象的內部具體實現的細節都是已知的。
屬性
用 ->(對象運算子):$this->property(其中 property 是該屬性名稱)這種方式來訪問非靜態屬性。靜態屬性則是用 ::(雙冒號):self::$property 來訪問
$this 是一個到主叫對象的引用
類常量
可以把在類中始終保持不變的值定義為常量。在定義和使用常量的時候不需要使用 $ 符號
常量的值必須是一個定值,不能是變數,類屬性,數學運算的結果或函數調用
用雙冒號::訪問
const constant = 'constant value';
自動載入類
很多開發人員寫物件導向的應用程式時對每個類的定義建立一個 PHP 源檔案。一個很大的煩惱是不得不在每個指令碼開頭寫一個長長的包含檔案清單(每個類一個檔案)。
在 PHP 5 中,不再需要這樣了。可以定義一個 spl_autoload_register() 函數,它會在試圖使用尚未被定義的類時自動調用。通過調用此函數,指令碼引擎在 PHP 出錯失敗前有了最後一個機會載入所需的類。
<?php// function __autoload($class) {// include 'classes/' . $class . '.class.php';// }function my_autoloader($class) { include 'classes/' . $class . '.class.php';}spl_autoload_register('my_autoloader');// 或者,自 PHP 5.3.0 起可以使用一個匿名函數spl_autoload_register(function ($class) { include 'classes/' . $class . '.class.php';});?>
建構函式和解構函式
建構函式和解構函式不會被引擎暗中調用。要執行父類的建構函式和解構函式,必須在子類的建構函式體和解構函式體中顯式調用 parent::__construct(); parent::__destruct()
繼承
除非使用了自動載入,否則一個類必須在使用之前被定義。如果一個類擴充了另一個,則父類必須在子類之前被聲明。此規則適用於類繼承其它類與介面。
繼承使用extends關鍵字
範圍解析操作符(::)
範圍解析操作符(也可稱作 Paamayim Nekudotayim)或者更簡單地說是一對冒號,可以用於訪問靜態成員,類常量
Static(靜態)關鍵字
聲明類屬性或方法為靜態,就可以不執行個體化類而直接存取。靜態屬性不能通過一個類已執行個體化的對象來訪問(但靜態方法可以)。
靜態屬性和方法預設為公有
抽象類別
使用關鍵字abstract
任何一個類,如果它裡面至少有一個方法是被聲明為抽象的,那麼這個類就必須被聲明為抽象的。
被定義為抽象的方法只是聲明了其調用方式(參數),不能定義其具體的功能實現。
繼承一個抽象類別的時候,子類必須定義父類中的所有抽象方法;另外,這些方法的存取控制必須和父類中一樣(或者更為寬鬆)
介面
介面是通過 interface 關鍵字
介面中定義的所有方法都必須是公有,這是介面的特性
介面中也可以定義常量。介面常量和類常量的使用完全相同,但是不能被子類或子介面所覆蓋
要實現一個介面,使用 implements 操作符。類中必須實現介面中定義的所有方法,否則會報一個致命錯誤。類可以實現多個介面,用逗號來分隔多個介面的名稱。
介面也可以繼承介面
Traits
自 PHP 5.4.0 起,PHP 實現了代碼複用的一個方法,稱為 traits。
<?phptrait ezcReflectionReturnInfo { function getReturnType() { /*1*/ } function getReturnDescription() { /*2*/ }}class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */}class ezcReflectionFunction extends ReflectionFunction { use ezcReflectionReturnInfo; /* ... */}?>
通過逗號分隔,在 use 聲明列出多個 trait
<?phptrait Hello { public function sayHello() { echo 'Hello '; }}trait World { public function sayWorld() { echo 'World'; }}class MyHelloWorld { use Hello, World; public function sayExclamationMark() { echo '!'; }}?>
魔術方法
__construct()
__destruct()
__call()
__callStatic()
__get()
__set()
__isset()
__unset()
__sleep() serialize() 函數會檢查類中是否存在一個魔術方法 __sleep()。如果存在,該方法會先被調用,然後才執行序列化操作。
__wakeup() unserialize() 會檢查是否存在一個 __wakeup() 方法。如果存在,則會先調用 __wakeup 方法
__toString() 用於一個類被當成字串時應怎樣回應
__invoke() 當嘗試以調用函數的方式調用一個對象時,__invoke() 方法會被自動調用
__set_state() 當調用 var_export() 匯出類時,此靜態 方法會被調用
__clone()
__debugInfo() var_dump()一個對象時調用
這些函數在 PHP 中被稱為”魔術方法”(Magic methods)。在命名自己的類方法時不能使用這些方法名,除非是想使用其魔術功能。
在給不可訪問屬性賦值時,__set() 會被調用。
讀取不可訪問屬性的值時,__get() 會被調用。
當對不可訪問屬性調用 isset() 或 empty() 時,__isset() 會被調用。
當對不可訪問屬性調用 unset() 時,__unset() 會被調用。
在對象中調用一個不可存取方法時,__call() 會被調用。
用靜態方式中調用一個不可存取方法時,__callStatic() 會被調用。
Final 關鍵字
如果父類中的方法被聲明為 final,則子類無法覆蓋該方法。如果一個類被聲明為 final,則不能被繼承。
屬性不能被定義為 final,只有類和方法才能被定義為 final
對象複製
對象複製可以通過 clone 關鍵字來完成(如果可能,這將調用對象的 __clone() 方法)。對象中的 __clone() 方法不能被直接調用。
對象比較
當使用比較子(==)比較兩個物件變數時,比較的原則是:如果兩個對象的屬性和屬性值 都相等,而且兩個對象是同一個類的執行個體,那麼這兩個物件變數相等。
而如果使用全等運算子(===),這兩個物件變數一定要指向某個類的同一個執行個體(即同一個對象)。
類型約束
PHP 5 可以使用類型約束。函數的參數可以指定必須為對象(在函數原型裡面指定類的名字),介面,數組(PHP 5.1 起)或者 callable(PHP 5.4 起)。不過如果使用 NULL 作為參數的預設值,那麼在調用函數的時候依然可以使用 NULL 作為實參。
類型約束不能用於標量類型如 int 或 string。Traits 也不允許。
類型約束不只是用在類的成員函數裡,也能使用在函數裡
對象序列化
所有php裡面的值都可以使用函數serialize()來返回一個包含位元組流的字串來表示。unserialize()函數能夠重新把字串變回php原來的值。 序列化一個對象將會儲存對象的所有變數,但是不會儲存對象的方法。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。