天天看點

php中類與面向對象

php中建立一個對象的方法

要建立一個類的執行個體,可以使用new關鍵字建立一個對象。

> $car = new Car(); //也可以采用變量來建立 Car為要執行個體化的類名
> 
> $className = 'Car';
> 
> $car = new $className();
           

類的屬性

public:公開的

protected:受保護的

private:私有的

預設都為public,外部可以通路。一般通過->對象操作符來通路對象的屬性或者方法,對于靜态屬性則使用::雙冒号進行通路。當在類成員方法内部調用的時候,可以使用$this僞變量調用目前對象的屬性。

$car = new Car();
echo $car->name;   //調用對象的屬性
echo $car->color;  //錯誤 受保護的屬性不允許外部調用

echo $car->price;  //錯誤 私有屬性不允許外部調用
           

受保護的屬性與私有屬性不允許外部調用,在類的成員方法内部是可以調用的。

class Car{
    private $price = '1000';
    public function getPrice() {
        return $this->price; //内部通路私有屬性
​    }
}
           

定義類的方法

通路控制的關鍵字代表的意義為:

public:公開的

protected:受保護的

private:私有的

我們可以這樣定義方法:

class Car {
    public function getName() {
        return '汽車';
    }
​}
$car = new Car();

echo $car->getName();
           

使用關鍵字static修飾的,稱之為靜态方法,靜态方法不需要執行個體化對象,可以通過類名直接調用,操作符為雙冒号::。

class Car {
    public static function getName() {
        return '汽車';
    }
​}
echo Car::getName(); //結果為“汽車”
           

構造函數和析構函數

PHP5可以在類中使用__construct()定義一個構造函數,具有構造函數的類,會在每次對象建立的時候調用該函數,是以常用來在對象建立的時候進行一些初始化工作。

class Car {
   function __construct() {
       print "構造函數被調用\n";
   }
}
$car = new Car(); //執行個體化的時候 會自動調用構造函數__construct,這裡會輸出一個字元串
           

在子類中如果定義了__construct則不會調用父類的__construct,如果需要同時調用父類的構造函數,需要使用parent::__construct()顯式的調用。

class Car {
   function __construct() {
       print "父類構造函數被調用\n";
   }
}
class Truck extends Car {
   function __construct() {
       print "子類構造函數被調用\n";
       parent::__construct();
   }
}
$car = new Truck();
           

同樣,PHP5支援析構函數,使用__destruct()進行定義,析構函數指的是當某個對象的所有引用被删除,或者對象被顯式的銷毀時會執行的函數。

class Car {
   function __construct() {
       print "構造函數被調用 \n";
   }
   function __destruct() {
       print "析構函數被調用 \n";
   }
}
$car = new Car(); //執行個體化時會調用構造函數
echo '使用後,準備銷毀car對象 \n';
unset($car); //銷毀時會調用析構函數
           

當PHP代碼執行完畢以後,會自動回收與銷毀對象,是以一般情況下不需要顯式的去銷毀對象。

Static靜态關鍵字

靜态屬性與方法可以在不執行個體化類的情況下調用,直接使用類名::方法名的方式進行調用。靜态屬性不允許對象使用->操作符調用。

class Car {
    private static $speed = ;

    public static function getSpeed() {
        return self::$speed;
    }
}
echo Car::getSpeed();  //調用靜态方法
           

靜态方法也可以通過變量來進行動态調用

$func = 'getSpeed';

$className = 'Car';

echo $className::$func();  //動态調用靜态方法
           

靜态方法中,$this僞變量不允許使用。可以使用self,parent,static在内部調用靜态方法與屬性。

class Car {
    private static $speed = ;

    public static function getSpeed() {
        return self::$speed;
    }

    public static function speedUp() {
        return self::$speed+=;
    }
}
class BigCar extends Car {
    public static function start() {
        parent::speedUp();
    }
}

BigCar::start();
echo BigCar::getSpeed();
           

通路控制

通路控制通過關鍵字public,protected和private來實作。被定義為公有的類成員可以在任何地方被通路。被定義為受保護的類成員則可以被其自身以及其子類和父類通路。被定義為私有的類成員則隻能被其定義所在的類通路。

類屬性必須定義為公有、受保護、私有之一。為相容PHP5以前的版本,如果采用 var 定義,則被視為公有。

class Car {
    $speed = ; //錯誤 屬性必須定義通路控制
    public $name;   //定義共有屬性
}
           

類中的方法可以被定義為公有、私有或受保護。如果沒有設定這些關鍵字,則該方法預設為公有。

class Car {
​    //預設為共有方法
    function turnLeft() {
    }
}
           

如果構造函數定義成了私有方法,則不允許直接執行個體化對象了,這時候一般通過靜态方法進行執行個體化,在設計模式中會經常使用這樣的方法來控制對象的建立,

比如單例模式隻允許有一個全局唯一的對象。
class Car {
    private function __construct() {
        echo 'object create';
    }

    private static $_object = null;
    public static function getInstance() {
        if (empty(self::$_object)) {
            self::$_object = new Car(); //内部方法可以調用私有方法,是以這裡可以建立對象
        }
        return self::$_object;
    }
}
//$car = new Car(); //這裡不允許直接執行個體化對象
$car = Car::getInstance(); //通過靜态方法來獲得一個執行個體
           

對象繼承

繼承是面向對象程式設計中常用的一個特性,汽車是一個比較大的類,我們也可以稱之為基類,除此之外,汽車還分為卡車、轎車、東風、寶馬等,因為這些子類具有很多相同的屬性和方法,可以采用繼承汽車類來共享這些屬性與方法,實作代碼的複用。

index.php
<?php
class Car {
    public $speed = ; //汽車的起始速度是0

    public function speedUp() {
        $this->speed += ;
        return $this->speed;
    }
}
//定義繼承于Car的Truck類
class Truck extends Car {
    public function speedUp() {
        $this->speed = parent::speedUp() + ;
    }
} 

$car = new Truck();
$car->speedUp();
echo $car->speed;
           

重載

PHP中的重載指的是動态的建立屬性與方法,是通過魔術方法來實作的。屬性的重載通過__set,__get,__isset,__unset來分别實作對不存在屬性的指派、讀取、判斷屬性是否設定、銷毀屬性。

class Car {
    private $ary = array();

    public function __set($key, $val) {
        $this->ary[$key] = $val;
    }

    public function __get($key) {
        if (isset($this->ary[$key])) {
            return $this->ary[$key];
        }
        return null;
    }

    public function __isset($key) {
        if (isset($this->ary[$key])) {
            return true;
        }
        return false;
    }

    public function __unset($key) {
        unset($this->ary[$key]);
    }
}
$car = new Car();
$car->name = '汽車';  //name屬性動态建立并指派
echo $car->name;
           

方法的重載通過__call來實作,當調用不存在的方法的時候,将會轉為參數調用__call方法,當調用不存在的靜态方法時會使用__callStatic重載。

class Car {
    public $speed = ;

    public function __call($name, $args) {
        if ($name == 'speedUp') {
            $this->speed += ;
        }
    }
}
$car = new Car();
$car->speedUp(); //調用不存在的方法會使用重載
echo $car->speed;
           

對象的進階特性

對象比較,當同一個類的兩個執行個體的所有屬性都相等時,可以使用比較運算符==進行判斷,當需要判斷兩個變量是否為同一個對象的引用時,可以使用全等運算符===進行判斷。

class Car {
}
$a = new Car();
$b = new Car();
if ($a == $b) echo '==';   //true
if ($a === $b) echo '==='; //false
           

對象複制,在一些特殊情況下,可以通過關鍵字clone來複制一個對象,這時__clone方法會被調用,通過這個魔術方法來設定屬性的值。

class Car {
    public $name = 'car';

    public function __clone() {
        $obj = new Car();
        $obj->name = $this->name;
    }
}
$a = new Car();
$a->name = 'new car';
$b = clone $a;
var_dump($b);
           

對象序列化,可以通過serialize方法将對象序列化為字元串,用于存儲或者傳遞資料,然後在需要的時候通過unserialize将字元串反序列化成對象進行使用。

class Car {
    public $name = 'car';
}
$a = new Car();
$str = serialize($a); //對象序列化成字元串
echo $str.'<br>';
$b = unserialize($str); //反序列化為對象
var_dump($b);