類和對(duì)象
類是面向?qū)ο蟪绦蛟O(shè)計(jì)的基本概念义锥,通俗的理解類就是對(duì)現(xiàn)實(shí)中某一個(gè)種類的東西的抽象
比如汽車可以抽象為一個(gè)類其屏,汽車擁有名字、輪胎缨该、速度偎行、重量等屬性,可以有換擋贰拿、前進(jìn)蛤袒、后退等操作方法。
對(duì)象通過new關(guān)鍵字進(jìn)行實(shí)例化類
class Car {
}
$car = new car();實(shí)例化
類的屬性
在類中定義的變量稱之為屬性膨更,通常屬性跟數(shù)據(jù)庫中的字段有一定的關(guān)聯(lián)妙真,因此也可以稱作“字段”。
屬性聲明是由關(guān)鍵字 public荚守,protected 或者 private 開頭珍德,后面跟一個(gè)普通的變量聲明來組成练般。屬性的變量可以設(shè)置初始化的默認(rèn)值,默認(rèn)值必須是常量
class Car {
//定義公共屬性
public $name = '汽車';
//定義受保護(hù)的屬性
protected $corlor = '白色';
//定義私有屬性
private $price = '100000';
}
1.默認(rèn)都為public锈候,外部可以訪問薄料。一般通過->對(duì)象操作符來訪問對(duì)象的屬性或者方法,
對(duì)于靜態(tài)屬性則使用::雙冒號(hào)進(jìn)行訪問泵琳。
當(dāng)在類成員方法內(nèi)部調(diào)用的時(shí)候摄职,可以使用$this偽變量調(diào)用當(dāng)前對(duì)象的屬性。
2.受保護(hù)的屬性與私有屬性不允許外部調(diào)用获列,在類的成員方法內(nèi)部是可以調(diào)用的
類的方法
方法就是在類中的function
在面向過程的程序設(shè)計(jì)中function叫做函數(shù)谷市,在面向?qū)ο笾衒unction則被稱之為方法。
同屬性一樣击孩,類的方法也具有public迫悠,protected 以及 private 的訪問控制
class Car {
public function getName() {
return '汽車';
}
}
$car = new Car();
echo $car->getName();
使用關(guān)鍵字static修飾的,稱之為靜態(tài)方法
靜態(tài)方法不需要實(shí)例化對(duì)象巩梢,可以通過類名直接調(diào)用及皂,操作符為雙冒號(hào)::
class Car {
public static function getName() {
return '汽車';
}
}
echo Car::getName(); //結(jié)果為“汽車”
類的方法之構(gòu)造函數(shù)和析構(gòu)函數(shù)
構(gòu)造函數(shù):實(shí)例化的時(shí)候 會(huì)自動(dòng)調(diào)用構(gòu)造函數(shù)__construct
class Car {
public function __construct() {
print "構(gòu)造函數(shù)被調(diào)用\n";
}
}
$car = new Car();
調(diào)用繼承父類的構(gòu)造函數(shù)使用parent::__construct()顯式的調(diào)用。
class Truck extends Car {
function __construct() {
print "子類構(gòu)造函數(shù)被調(diào)用\n";
parent::__construct();
}
}
$car = new Truck();
析構(gòu)函數(shù)指的是當(dāng)某個(gè)對(duì)象的所有引用被刪除且改,或者對(duì)象被顯式的銷毀時(shí)會(huì)執(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(); //實(shí)例化時(shí)會(huì)調(diào)用構(gòu)造函數(shù)
echo '使用后,準(zhǔn)備銷毀car對(duì)象 \n';
unset($car); //銷毀時(shí)會(huì)調(diào)用析構(gòu)函數(shù)
類的關(guān)鍵字static
靜態(tài)屬性與方法可以在不實(shí)例化類的情況下調(diào)用又跛,直接使用類名::方法名的方式進(jìn)行調(diào)用碍拆。靜態(tài)屬性不允許對(duì)象使用->操作符調(diào)用。
class Car {
private static $speed = 10;
public static function getSpeed() {
return self::$speed;
}
}
echo Car::getSpeed(); //調(diào)用靜態(tài)方法
靜態(tài)方法中慨蓝,$this偽變量不允許使用感混。可以使用self礼烈,parent弧满,static在內(nèi)部調(diào)用靜態(tài)方法與屬性。
訪問控制
訪問控制通過關(guān)鍵字public此熬,protected和private來實(shí)現(xiàn)庭呜。
1.被定義為 公有的類 成員可以在任何地方被訪問。
2.被定義為 受保護(hù)的類 成員則可以被其自身以及其子類和父類訪問犀忱。
3.被定義為 私有的類 成員則只能被其定義所在的類訪問募谎。
重載
PHP中的重載指的是動(dòng)態(tài)的創(chuàng)建屬性與方法,是通過魔術(shù)方法來實(shí)現(xiàn)的阴汇。
- 屬性重載:
通過__set数冬,__get,__isset搀庶,__unset來分別實(shí)現(xiàn)對(duì)不存在屬性的賦值拐纱、讀取铜异、判斷屬性是否設(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屬性動(dòng)態(tài)創(chuàng)建并賦值
echo $car->name; //汽車
- 方法重載:
通過__call來實(shí)現(xiàn)揍庄,當(dāng)調(diào)用不存在的方法的時(shí)候,將會(huì)轉(zhuǎn)為參數(shù)調(diào)用__call方法咕宿,當(dāng)調(diào)用不存在的靜態(tài)方法時(shí)會(huì)使用__callStatic重載。
class Car {
public $speed = 0;
public function __call($name, $args) {
if ($name == 'speedUp') {
$this->speed += 10;
}
}
}
$car = new Car();
$car->speedUp(); //調(diào)用不存在的方法會(huì)使用重載
echo $car->speed; //10
對(duì)象高級(jí)特性
- 對(duì)象比較
1.當(dāng)同一個(gè)類的兩個(gè)實(shí)例的所有屬性都相等時(shí)蜡秽,可以使用比較運(yùn)算符==進(jìn)行判斷府阀,
2.當(dāng)需要判斷兩個(gè)變量是否為同一個(gè)對(duì)象的引用時(shí),可以使用全等運(yùn)算符===進(jìn)行判斷芽突。
class Car {
}
$a = new Car();
$b = new Car();
if ($a == $b) echo '=='; //true
if ($a === $b) echo '==='; //false
- 對(duì)象復(fù)制
關(guān)鍵字clone來復(fù)制一個(gè)對(duì)象试浙,這時(shí)__clone方法會(huì)被調(diào)用,通過這個(gè)魔術(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);
object(Car)#2 (1) {
["name"]=>
string(7) "new car"
}
- 對(duì)象序列化
serialize方法將對(duì)象序列化為字符串田巴,用于存儲(chǔ)或者傳遞數(shù)據(jù)
通過unserialize將字符串反序列化成對(duì)象進(jìn)行使用
class Car {
public $name = 'car';
}
$a = new Car();
$str = serialize($a); //對(duì)象序列化成字符串
echo $str.'<br>';
$b = unserialize($str); //反序列化為對(duì)象
var_dump($b);
異常處理
基本語法
try{
//可能出現(xiàn)錯(cuò)誤或異常的代碼
//catch表示捕獲,Exception是php已定義好的異常類
} catch(Exception $e){
//對(duì)異常處理挟秤,方法:
//1壹哺、自己處理
//2、不處理艘刚,將其再次拋出
}
既然拋出異常會(huì)中斷程序執(zhí)行管宵,那么為什么還需要使用異常處理?
異常拋出被用于在遇到未知錯(cuò)誤攀甚,或者不符合預(yù)先設(shè)定的條件時(shí)箩朴,通知客戶程序,以便進(jìn)行其他相關(guān)處理秋度,不至于使程序直接報(bào)錯(cuò)中斷炸庞。
異常處理類
Exception是所有異常處理的基類。
Exception具有幾個(gè)基本屬性與方法:
- message 異常消息內(nèi)容
- code 異常代碼
- file 拋出異常的文件名
- line 拋出異常在該文件的行數(shù)
常用方法:
getTrace 獲取異常追蹤信息
getTraceAsString 獲取異常追蹤信息的字符串
getMessage 獲取出錯(cuò)信息
只有在極端情況或者非常重要的情況下荚斯,才會(huì)拋出異常
一般的異常處理流程代碼為:
try {
throw new Exception('wrong');
} catch(Exception $ex) {
$msg = 'Error:'.$ex->getMessage()."\n";
$msg.= $ex->getTraceAsString()."\n";
$msg.= '異常行號(hào):'.$ex->getLine()."\n";
$msg.= '所在文件:'.$ex->getFile()."\n";
//將異常信息記錄到日志中
PHP異常處理之 file_put_contents('error.log', $msg);
}
echo '異常處理后埠居,繼續(xù)執(zhí)行其他代碼';
正則表達(dá)式
正則匹配模式
PCRE庫函數(shù)
正則匹配模式使用分隔符與元字符組成,分隔符可以是非數(shù)字事期、非反斜線拐格、非空格的任意字符。
分隔符是正斜線(/)刑赶、hash符號(hào)(#) 捏浊、以及取反符號(hào)(~)
/foo bar/
#^[^0-9]$#
~php~
元字符
常用元字符
\ 一般用于轉(zhuǎn)義字符
^ 斷言目標(biāo)的開始位置(或在多行模式下是行首)
$ 斷言目標(biāo)的結(jié)束位置(或在多行模式下是行尾)
. 匹配除換行符外的任何字符(默認(rèn))
[ 開始字符類定義
] 結(jié)束字符類定義
| 開始一個(gè)可選分支
( 子組的開始標(biāo)記
) 子組的結(jié)束標(biāo)記
? 作為量詞,表示 0 次或 1 次匹配撞叨。位于量詞后面用于改變量詞的貪婪特性金踪。 (查閱量詞)
* 量詞浊洞,0 次或多次匹配
+ 量詞,1 次或多次匹配
{ 自定義量詞開始標(biāo)記
} 自定義量詞結(jié)束標(biāo)記
以下來自PHP5權(quán)威編程
靜態(tài)屬性
屬于類本身而非是類的實(shí)例
相當(dāng)于是存儲(chǔ)在類的全局變量胡岔,可以通過類在任何地方訪問
由關(guān)鍵字 static定義
訪問:
類名::定義靜態(tài)名
Person:: $name
靜態(tài)方法
訪問:class_name::method
常量
與靜態(tài)成員類似 屬于類的本身不是屬于類的實(shí)例
訪問:self::常量名[規(guī)范大寫]
self:: parent::
self 指向當(dāng)前的類 用于訪問靜態(tài)屬性法希、方法、常量
parent 指向父類 用于調(diào)用父類的構(gòu)造函數(shù)和方法
instance of 邏輯二元運(yùn)算符
用于確定一個(gè) PHP 變量是否屬于某一類 [class]
_CLASS_ 用于存儲(chǔ)當(dāng)前類名
Abstract 抽象方法和抽象類
抽象類不能夠被實(shí)例化/初始化靶瘸,但是可以依靠具體類的繼承來實(shí)現(xiàn)苫亦。
繼承的子類必須實(shí)現(xiàn)了抽象類中的所有抽象方法,否則會(huì)報(bào)錯(cuò)
如果子類沒有全部實(shí)現(xiàn)抽象類中的所有抽象方法怨咪,那么該子類也是一個(gè)抽象類屋剑,必須在 class 前面加上 abstract 關(guān)鍵字,并且不能被實(shí)例化
定義:
class 前加了 abstract 關(guān)鍵字且存在抽象方法
(在類方法 function 關(guān)鍵字前加了 abstract 關(guān)鍵字)的類诗眨。
abstract class A
{
/** 抽象類中可以定義變量 */
protected $value1 = 0;
private $value2 = 1;
public $value3 = 2;
/** 也可以定義非抽象方法 */
public function my_print()
{
echo "hello,world/n";
}
/**
* 大多數(shù)情況下唉匾,抽象類至少含有一個(gè)抽象方法。
抽象方法用abstract關(guān)鍵字聲明匠楚,其中不能有具體內(nèi)容巍膘。
* 可以像聲明普通類方法那樣聲明抽象方法,
但是要以分號(hào)而不是方法體結(jié)束芋簿。
也就是說抽象方法在抽象類中不能被實(shí)現(xiàn)峡懈,也就是沒有函數(shù)體“{some codes}”。
*/
abstract protected function abstract_func1();
abstract protected function abstract_func2();
}
//部分繼承抽象類A与斤,且不能實(shí)例化
abstract class B extends A
{
public function abstract_func1()
{
echo "implement the abstract_func1 in class A/n";
}
/** 這么寫在zend studio 8中會(huì)報(bào)錯(cuò)
//abstract protected function abstract_func2();
遵循以下規(guī)則:
B類的成員訪問控制不能比A類嚴(yán)格
A->public B->public
A->protected B->public逮诲、protected
A不能定義為 private
( Fatal error : Abstract function A::abstract_func() cannot be declared private )
*/
}
class C extends B
{
public function abstract_func2()
{
echo "implement the abstract_func2 in class A/n";
}
}
interface 接口
參考文章:
interface abstract 不同點(diǎn)和相同點(diǎn)參考文章
interface 是完全抽象的,只能聲明方法幽告,而且只能聲明 public 的方法梅鹦,不能聲明 private 及 protected 的方法,不能定義方法體冗锁,也不能聲明實(shí)例變量 齐唆。然而, interface 卻可以聲明常量變量
interface iA
{
const AVAR=3;
public function iAfunc1();
public function iAfunc2();
}
echo iA:: AVAR;
任何實(shí)現(xiàn)接口的類都要實(shí)現(xiàn)接口中所定義的所有方法,否則要聲明為abstract類
class E implements iA
{
public function iAfunc1(){echo "in iAfunc1";}
public function iAfunc2(){echo "in iAfunc2";}
}
abstract class E implements iA{}
類可以在聲明中使用 implements 關(guān)鍵字來實(shí)現(xiàn)某個(gè)接口
interface iB
{
public function iBfunc1();
public function iBfunc2();
}
class D extends A implements iA,iB
{
public function abstract_func1()
{
echo "implement the abstract_func1 in class A/n";
}
public function abstract_func2()
{
echo "implement the abstract_func2 in class A/n";
}
public function iAfunc1(){echo "in iAfunc1";}
public function iAfunc2(){echo "in iAfunc2";}
public function iBfunc1(){echo "in iBfunc1";}
public function iBfunc2(){echo "in iBfunc2";}
}
類可以同時(shí)繼承一個(gè)父類和實(shí)現(xiàn)任意多個(gè)接口
class D extends B implements iA,iB
{
public function abstract_func1()
{
parent::abstract_func1();
echo "override the abstract_func1 in class A/n";
}
public function abstract_func2()
{
echo "implement the abstract_func2 in class A/n";
}
public function iAfunc1(){echo "in iAfunc1";}
public function iAfunc2(){echo "in iAfunc2";}
public function iBfunc1(){echo "in iBfunc1";}
public function iBfunc2(){echo "in iBfunc2";}
}
final方法和類
final方法:確保一個(gè)方法不被繼承類改寫
final類:確保一個(gè)類不被繼承