-
-
class Myclass{
- public $prop = 123;
- }
-
$obj = new Myclass();
- ?>
-
複製程式碼
類別的成員屬性(屬性的稱呼相對於「方法」而言)包括類別常數和類別變量,其中類別常數在定義時不可為空,類別的屬性在定義時如果被賦值,只能使用標量和數組,並且不能是表達式,因為類別屬性在編譯期被初始化,PHP 在編譯期不執行表達式。
1、成員的存取控制:
public:可以繼承,可以在類別的方法之外被存取 , 如 $obj->prop;
protected:可以繼承,不可以在類別的方法之外被訪問
private:不可以繼承,不可以在類別的方法之外存取
PHP 4 使用 var 來聲明類別的屬性,在PHP5之後不再使用,PHP5.3之前使用被警告,PHP5.3之後可以用在 public 之前或單獨使用作為 public 的別名。
這三個存取控制關鍵字也可以修飾建構函數,當private 和protected 修飾類別的建構子時,你只能透過一個publice static 的靜態方法來呼叫建構子以實例化對象,因為夠在函數無法在類別之外被存取了,例如,單例類別的實作:
-
-
class Singleton {
- private static $instance=null;
- public $k = 88;
- private function __construct(){
}
public static function getInstance(){
- if(self::$instance= =null){
- self::$instance = new self();
- }
return self::$instance;
- }
-
public function __clone(){ //pretend clone oprationg
- throw('Singleton class can not be cloned');
- return self::getInstance();
- }
- }>} p>
//new Singleton(); // Error
- $in = Singleton::getInstance();
- ?>
-
複製程式碼
2、繼承禁止: final 關鍵字,僅用於修飾類別或類別的方法
如果一個類別被 final 修飾,這個類別不能被繼承,如果一個方法被final 修飾,則這個方法不能被子類別重寫(override)。
-
-
class Myclass{
- public $prop = 123;
- final public static function methodA(){///不可繼承的,公開的靜態方法
- return 'this is a final method';
- }
- }
- ?>
複製代碼
3、抽象類別和抽象方法:abstract 僅用於類別和方法,抽象類別不能直接用於實例化物件只能用於產生子類
-
-
abstract class Myclass{
- public $prop = 123;
- abstract public function methodA() //抽象;方法沒有實作函數體
- }
- ?>
複製程式碼
4、類別的常數及其存取 4、類別的常數及其存取
4、類別的常數及其存取-
-
- 4、類別的常數>
- :類別的常數不能使用存取限制修飾符,他是public 的,可繼承,可以被子類別重寫,存取類別的常數必須使用雙冒號:: ,可以使用類別名稱或類別的實例來存取。
-
-
-
-
-
-
class Myclass{
- public $prop = 123;
- const x =999;
public static function methodA(){
- return 'this is a final method';
- }
public function getConst(){
- return self::x; //或$this::x;
- }
}
$instance = new Myclass();
echo Myclass::x; echo $instance::x; echo $instance->getConst();?> 複製程式碼類別的常數是一個值,在程式碼編譯期常數名被替換為對應的值,在運行期不可修改,因此,類別的常數是與類別本身相關,在實例化物件之前就已經存在了,因此類別的常數可以直接使用類別名稱存取。
-
-
class P{
- const m = 100;
- const n = p = :: m;
- }
class S extends P{
- const m=200;
- public function getPConst(){
- return parent::n;
- }
- }
$p = new P();
- $s = new S();
- echo $p::n; //100
- echo $s::n; //200 此常數名稱是繼承自父類,在編譯期取self::m 的值替換,注意區別類別的方法使用self::m
echo $s->getPConst(); //100
- ?>
-
複製程式碼
5、類別的靜態成員及訪問
static 可以修飾類別的屬性及方法,被static 修飾的成員屬於類別而不屬於類別的實例,靜態成員必須使用類別名稱加雙冒號:: 來訪問, 因為在實例化物件之前靜態成員就存在了,因此,在靜態方法內,禁止使用指向實例本身的偽變量$this(或習慣上稱為$this 指針) ,可以使用關鍵字self 代替類名(相當於類的魔術常數__CLASS__)。
static 不能用來修飾 類別的建構函數,也不能用來修飾介面宣告的方法。
-
-
class Myclass{
- public static $x = 99;
-
public function getX(){
- return self::$x;
- }
- }
echo Myclass::x; //99
- ? >
-
複製程式碼
靜態成員可以使用存取控制關鍵字修飾,可以被繼承和重寫,需要注意的是,如果一個子類別繼承了父類別的靜態方法(沒有重寫該方法),那麼子類別呼叫的實際上是父類別的靜態方法。因為靜態成員持有者是類別不是對象,所以類別的多個實例是共享同一個靜態屬性的,在一個實例中修改靜態屬性會影響到另一個實例中的靜態屬性:
-
-
class A{
public static $a1 = 11;
- public $a2 = 22;
public static function showStatic(){
- return self::$a1;
- }
public function getStatic(){
- return self::$a1;
- }
public function getClassStatic(){
- $className = get_called_class();
- return
- return
- $className::$a1;
- }
public function getProp(){
- return $this->a2;
- }
- }
class B extends A{
- public static $a1 = 88;
- public $a2 = 99;
- }
$obj1 = new A() ;
- $obj2 = new B();
echo A::showStatic(); //11
- echo $obj1->getStatic(); //11
- echo $obj1->getClassStatic(); //11
- echo $obj1->getProp(); //22
echo B::showStatic(); //11 呼叫的是父類別的方法,存取父類別的靜態成員
- echo $obj2->getStatic(); //11 呼叫的是父類別的方法,方法中的self 指向持有該靜態方法的類別
- echo $obj2->getClassStatic(); //88
- echo $obj2->getProp(); //99
- ?>
複製程式碼後期靜態綁定:為了避免子類別重寫靜態屬性後,使用繼承來的方法仍然存取父類別的靜態屬性, PHP5.3 增加了一個新的語法:後期靜態綁定,使用static 關鍵字取代self 關鍵字,使得static 指向與get_called_class() 傳回的相同的類,即當前呼叫該靜態方法的物件所屬的類,該關鍵字對於靜態方法的存取同樣有效。
-
-
public function getClassStatic(){
- $className = get_called_class() }
//可以寫成:
- public function getClassStatic(){
- return static::$a1;
- }
//用於靜態方法
- //A類別中:
- public static function testStatic(){
- echo "
testStatic of A " ;
- }
public function callStatic(){
- static::testStatic();
- }
//B類中:
- public static function testStatic(){
- echo "
testStatic of B ";
- }
- //B類別繼承A類別的callStatic 方法,可以正確存取各自類別的testStatic 方法。
- ?>
-
-
複製程式碼
6、類別的方法中幾個指向類別或實例的關鍵字
$this->propName $this 指向類別的實例
parent::xxx parent 指向父類,可以存取父類別的靜態常數、靜態屬性(parent::$xxx) ,不能存取父類別的非靜態屬性,可以呼叫父類別的方法(不能是private 方法,無論是否靜態)
self::xxx self 指向定義了目前被呼叫的方法的類,用於存取靜態成員和類別的常數
static::xxx 存取實例化了呼叫當前方法的實例的那個類,用於訪問靜態成員和累的常數,他跟 self 的差別是訪問靜態成員時採用 “後期靜態綁定”。
7、類別的繼承中的 重寫問題:
重寫的成員的存取控製程度不能被縮小,例如, public 的成員不能重寫為 protected
非靜態成員不能改寫為靜態成員,靜態成員也不能改寫為非靜態成員
8、介面中定義的方法必須是 public
類別在實作介面的方法時,這些方法也必須是 public 的,具體實作的(不能是 abstract )。
介面也可以定義介面常數,用法與類別常數完全一致,但是介面不可以定義非函數成員。
介面與介面之間可以繼承,介面的繼承可以是多繼承,用逗號隔開(字類別與父類別的繼承是單繼承的)
一個類別可以實現多個接口,用逗號隔開
-
interface Ix extends Iy,Iz{
- public function a();
- }
- }
- class A implements Iy,Iz{
- .......
- }
- ?>
-
複製程式碼
9、模式約束
PHP 的函數(或類別的方法) 可以在宣告時限定參數的類型,但只能限定array 或object(class/interface) ,如果限定為string 型, PHP 會認為是限定為一個string 類別的object 參數。
如果類型被限定為某個接口,則傳入的參數必須是實作該介面的類別的實例。
在介面實作、子類別重寫父類別方法時,不能修改已經限定的參數類型。
在方法、函數呼叫時,如果傳入了與限定的參數類型不同的資料將會報錯,但是可以接受 null 參數。
-
interface Im{
- public function a( classm $m);
- }
- }
class A implements Im{
- public function a($x){ // error ,參數$x必須限定為classm 類型以符合介面的定義
- var_dump($x) ;
- }
- }
- ?>
-
複製程式碼
|