類和對象
類是面向?qū)ο蟪绦蛟O(shè)計的基本概念。類是一類東西的結(jié)構(gòu)描述策精,而對象則是一類東西的一個具體實例舰始。
通俗的理解:汽車可以抽象為一個類,汽車擁有名字咽袜、輪胎丸卷、速度、重量等屬性询刹,可以有換擋谜嫉、前進、后退等操作方法凹联。而我的Fiat 500C沐兰,你的Porsche或Golf都是類具體化之后的對象。
// 定義一個汽車類
class Car {
$name = '汽車';
function getName() {
return $this->name;
}
}
// 通過new關(guān)鍵字對類進行實例化
$car = new Car();
echo $car->getName();
語法:
//定義一個類
class Car {
//定義屬性
public $name = '汽車';
//定義方法
public function getName() {
//方法內(nèi)部可以使用$this偽變量調(diào)用對象的屬性或者方法
return $this->name;
}
}
類的屬性
在類中定義的變量稱之為屬性匕垫。屬性聲明是由關(guān)鍵字public
僧鲁,protected
或者 private
開頭,后面跟一個普通的變量聲明來組成。
public:公開的
protected:受保護的
private:私有的
注意:外部只能訪問public屬性寞秃,protected和private都不允許外部的訪問U宓稹!
舉例:
class Car {
//定義公共屬性
public $name = '汽車';
//定義受保護的屬性
protected $corlor = '白色';
//定義私有屬性
private $price = '100000';
}
$car = new Car();
echo $car->name; //調(diào)用對象的屬性
echo $car->color; // ! 錯誤 受保護的屬性不允許外部調(diào)用
echo $car->price; // ! 錯誤 私有屬性不允許外部調(diào)用
類的方法
方法就是在類中的function春寿,很多時候我們分不清方法與函數(shù)有什么差別朗涩,在面向過程的程序設(shè)計中function叫做函數(shù),在面向?qū)ο笾衒unction則被稱之為方法绑改。
同屬性一樣谢床,類的方法也具有public
,protected
以及private
的訪問控制厘线。
舉例:
class Car {
public $speed = 0;
//增加speedUp方法识腿,使speed加10
public function speedUp(){
$this->speed+=10;
}
}
$car = new Car();
$car->speedUp();
echo $car->speed;
構(gòu)造函數(shù)
PHP5在類中使用__construct()
定義一個構(gòu)造函數(shù):會在每次對象創(chuàng)建的時候調(diào)用該函數(shù),因此常用來在對象創(chuàng)建的時候進行一些初始化工作造壮。
class Car {
function __construct() {
print "構(gòu)造函數(shù)被調(diào)用\n";
}
}
$car = new Car(); // 實例化的時候 會自動調(diào)用構(gòu)造函數(shù)__construct渡讼,這里會輸出一個字符串
注意:在子類中如果定義了__construct
則不會調(diào)用父類的__construct
,如果需要同時調(diào)用父類的構(gòu)造函數(shù)耳璧,需要使用parent::__construct()
顯式的調(diào)用成箫。
class Car {
function __construct() {
print "父類構(gòu)造函數(shù)被調(diào)用\n";
}
}
class Truck extends Car {
function __construct() {
print "子類構(gòu)造函數(shù)被調(diào)用\n";
parent::__construct();
}
}
$car = new Truck();
析構(gòu)函數(shù)
PHP5支持析構(gòu)函數(shù),使用__destruct()
進行定義旨枯,析構(gòu)函數(shù)指的是當(dāng)某個對象的所有引用被刪除蹬昌,或者對象被顯式的銷毀時會執(zhí)行的函數(shù)。
class Car {
function __construct() {
print "構(gòu)造函數(shù)被調(diào)用 \n";
}
function __destruct() {
print "析構(gòu)函數(shù)被調(diào)用 \n";
}
}
$car = new Car(); //實例化時會調(diào)用構(gòu)造函數(shù)
echo '使用后攀隔,準(zhǔn)備銷毀car對象 \n';
unset($car); //銷毀時會調(diào)用析構(gòu)函數(shù)
Tipp: 當(dāng)PHP代碼執(zhí)行完畢以后皂贩,會自動回收與銷毀對象,因此一般情況下不需要顯式的去銷毀對象竞慢。
Static 靜態(tài)
靜態(tài) 屬性與方法可以在不實例化類的情況下調(diào)用先紫,直接使用類名::方法名
的方式進行調(diào)用治泥。
class Car {
private static $speed = 10;
public static function getSpeed() {
return self::$speed;
}
}
echo Car::getSpeed();
靜態(tài)方法也可以通過變量來進行動態(tài)/可變調(diào)用:
$func = 'getSpeed';
$className = 'Car';
echo $className::$func(); //動態(tài)調(diào)用靜態(tài)方法
注意:
1)靜態(tài)屬性不允許對象使用->
操作符調(diào)用筹煮。用::
代替
2)靜態(tài)方法中,$this
偽變量不允許使用居夹“芰剩可以使用self
,parent
准脂,static
在內(nèi)部調(diào)用靜態(tài)方法與屬性劫扒。
class Car {
private static $speed = 10;
public static function getSpeed() {
return self::$speed;
}
public static function speedUp() {
return self::$speed+=10;
}
}
class BigCar extends Car {
public static function start() {
parent::speedUp();
}
}
BigCar::start();
echo BigCar::getSpeed();
訪問控制
前面的小節(jié),我們已經(jīng)接觸過訪問控制了狸膏,訪問控制通過關(guān)鍵字public
沟饥,protected
和private
來實現(xiàn)。
public:可以在任何地方被訪問
protected:可以被其自身以及其子類和父類訪問
private:只能被其定義所在的類訪問
注意: 類屬性和方法必須定義為公有、受保護贤旷、私有之一广料。未定義的情況下,兩者默認都為public幼驶。
私人構(gòu)造函數(shù) private function __construct
如果構(gòu)造函數(shù)定義成了私有艾杏,則不允許直接實例化對象了。
==> 這時候一般通過 靜態(tài)方法getInstance()
進行實例化
在設(shè)計模式中會經(jīng)常使用這樣的方法來控制對象的創(chuàng)建盅藻,比如單例模式只允許有一個全局唯一的對象购桑。
舉例:
class Car {
private function __construct() {
echo 'object create';
}
private static $_object = null;
public static function getInstance() {
if (empty(self::$_object)) {
self::$_object = new Car(); //內(nèi)部方法可以調(diào)用私有方法,因此這里可以創(chuàng)建對象
}
return self::$_object;
}
}
//$car = new Car(); //這里不允許直接實例化對象
$car = Car::getInstance(); //通過靜態(tài)方法來獲得一個實例
繼承
繼承是面向?qū)ο蟪绦蛟O(shè)計中常用的一個特性氏淑,汽車是一個比較大的類勃蜘,我們也可以稱之為基類,除此之外假残,汽車還分為卡車元旬、轎車,因為這些子類具有很多相同的屬性和方法守问,可以采用繼承汽車類來共享這些屬性與方法匀归,實現(xiàn)代碼的復(fù)用。
舉例:Truck的速度比基類Car的速度快50耗帕。
class Car {
public $speed = 0; //汽車的起始速度是0
public function speedUp() {
$this->speed += 10;
return $this->speed;
}
}
//定義繼承于Car的Truck類
class Truck extends Car{
public function speedUp(){
$this->speed=parent::speedUp() + 50;
}
}
$car = new Truck();
$car->speedUp();
echo $car->speed;
重載
PHP中的重載指的是動態(tài)的創(chuàng)建屬性與方法穆端,是通過魔術(shù)方法來實現(xiàn)的。
1)屬性的重載
通過__set
仿便,__get
体啰,__isset
,__unset
來分別實現(xiàn)對不存在屬性的賦值嗽仪、讀取荒勇、判斷屬性是否設(shè)置、銷毀屬性闻坚。
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屬性動態(tài)創(chuàng)建并賦值
echo $car->name;
2)方法的重載
方法的重載通過__call
來實現(xiàn)沽翔,
=> 調(diào)用不存在的方法的時候,將會轉(zhuǎn)為參數(shù)調(diào)用__call方法
=> 調(diào)用不存在的靜態(tài)方法 時會使用__callStatic
重載窿凤。
class Car {
public $speed = 10;
//在這里使用重載實現(xiàn)speedDown方法
public function __call($name, $args){
if($name == 'speedDown'){
$this->speed-=10;
}
}
}
$car = new Car();
$car->speedDown(); //調(diào)用不存在的speedDown方法
echo $car->speed;
對象復(fù)制
在一些特殊情況下仅偎,可以通過關(guān)鍵字clone
來復(fù)制一個對象,這時__clone
方法會被調(diào)用雳殊,通過這個魔術(shù)方法來設(shè)置屬性的值橘沥。
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
方法將對象 序列化 為字符串夯秃,用于存儲或者傳遞數(shù)據(jù)座咆,然后在需要的時候通過unserialize
將字符串 反序列化 成對象進行使用痢艺。
class Car {
public $name = 'car';
}
$a = new Car();
$str = serialize($a); //對象序列化成字符串
echo $str.'<br>';
$b = unserialize($str); //反序列化為對象
var_dump($b);