5-php面向?qū)ο?/h1>

什么是面向?qū)ο螅?/h1>

面向?qū)ο笫且环N先進(jìn)的編程模型腿准,相對(duì)于面向過程編程,面向?qū)ο蟾哂羞壿嬓允奥担钩绦虼a更加的健壯吐葱、易于維護(hù)和好擴(kuò)展。被稱為 OOP編程(Object Oriented Programming)校翔。


面向?qū)ο缶幊?/div>

面向?qū)ο缶哂蟹庋b弟跑、繼承、多態(tài)三大特性

1. 封裝:

所有的常量防症、變量和函數(shù)都要寫在類的內(nèi)部孟辑,歸屬于這個(gè)類,代碼不能寫在類的外部蔫敲。
注意:因?yàn)镻HP是從面向過程發(fā)展過來的饲嗽,所以PHP里面支持兩種寫法,PHP變量奈嘿、函數(shù)等等代碼也可以寫在類的外面貌虾,但如果是一個(gè)門純的OOP的語(yǔ)言,比如Java裙犹,所有代碼必須寫在類里面尽狠,任何東西不能放在類的外面。

2. 繼承:

一個(gè)類A可以繼承自另一個(gè)類B叶圃,繼承之后袄膏,這個(gè)類A【一般被稱為子類】中就擁有了那個(gè)B類【一般被稱為父類】中的屬性和方法庐杨。
注意:比如寫了一個(gè)類實(shí)現(xiàn)一個(gè)功能冠胯,然后想添加更多新功能,那么可以直接再定義一個(gè)子類繼承自這個(gè)類危虱,然后在子類中添加新功能赫舒,這樣在不修改原代碼的基礎(chǔ)上添加新功能悍及。

3. 多態(tài):

同一個(gè)類的子類中的同一個(gè)方法會(huì)表現(xiàn)出不同的行為,比如:人都會(huì)走路接癌,但不同的人走路的姿勢(shì)是不一樣的心赶,這里的人就是父類,子類是不同的人缺猛,雖然都有同一個(gè)“走路”的方法缨叫,但不同的人走路的方式是不一樣。

語(yǔ)法定義

在面向?qū)ο笾兴械拇a都要封裝在一個(gè)類中荔燎。
定義類的語(yǔ)法:

<?php 

class 類名
{
    代碼;
}

?>

類名由數(shù)字耻姥、字母和下劃線組成,不能使用數(shù)字開頭有咨。
業(yè)內(nèi)慣例:類名首字母大寫琐簇。后面的單詞首字母大寫。

<?php 

/**
 * UserInfo類
 */
class UserInfo
{

    //.... 這里書寫代碼

}

?>

類的常量座享、屬性和方法

常量

在類中值不會(huì)改變的量婉商,可以定義成類常量,類常量不需要使用 $ 符渣叛。


<?php 

/**
 * Math數(shù)學(xué)類
 */
class Math
{
    // 定義常量 不需要使用$丈秩,并且以后值不能改變
    const PI = 3.1415926;
}

// 調(diào)用語(yǔ)法
echo Math::PI;
 ?>

屬性

在類中可以定義變量,習(xí)慣叫它為類的屬性淳衙。
定義屬性時(shí)前面要加上public蘑秽、protected或者private。如果沒有加PHP認(rèn)為是public的箫攀。

<?php 
/**
 * People類
 */
class People
{
    public $username;
    protected $age;
    private $salary;

}

 ?>

注意:也可以使用var筷狼,這個(gè)是PHP4時(shí)候的寫法,相當(dāng)于 public匠童。

<?php 
/**
 * People類
 */
class People
{
    var $username;
    var $age;
    private $salary;

}

 ?>

注意:定義屬性的時(shí)候可以進(jìn)行初始化賦值操作埂材。


<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

}

 ?>

方法

類中也可以定義函數(shù),稱為類的方法汤求。
定義函數(shù)前面也要加上public俏险、protected或者private。如果不加認(rèn)為是public的扬绪。


<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        
    }


}

 ?>

對(duì)象

一個(gè)類是不能使用的竖独,如果要使用類里面的代碼,必須要先new一個(gè)對(duì)象出來挤牛,然后使用這個(gè)對(duì)象來調(diào)用里面的代碼莹痢。

<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        
    }


}

$p1 = new People();
var_dump($p1->username);

 ?>

類和對(duì)象的關(guān)系

類相當(dāng)于圖紙,用來描述都有哪些功能和特征,對(duì)象就是有真正有這些功能和特征的物品竞膳。
一個(gè)類可以生成多個(gè)對(duì)象航瞭,每個(gè)對(duì)象是彼此獨(dú)立的個(gè)體,互不影響坦辟。

類和對(duì)象

$this

在類中可以使用一個(gè)特殊變量$this刊侯,代表調(diào)用這個(gè)方法的那個(gè)對(duì)象。
簡(jiǎn)單點(diǎn)說:類里面要使用類中的屬性必須使用$this就這樣锉走。

<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        return $this->username; // $this代表當(dāng)前對(duì)象
    }


}

$p1 = new People();
var_dump( $p1->getName() );
 ?>

對(duì)象默認(rèn)都是按引入傳遞的【不需要加&】


<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        return $this->username; // $this代表當(dāng)前對(duì)象
    }


}

$p1 = new People();

$p2 = $p1; // 指向的是同一個(gè)地址空間
$p2->username = 'p2Username';

var_dump($p1->username);
 ?>

注意:
如果就想要拷貝一個(gè)新的出來而不是引入同一個(gè):可以使用clone來克一個(gè)新對(duì)象


<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        return $this->username; // $this代表當(dāng)前對(duì)象
    }


}

$p1 = new People();

$p2 = clone $p1; // 復(fù)制一個(gè)對(duì)象滨彻,指向的不是同一個(gè)地址空間
$p2->username = 'p2Username';

var_dump($p1->username);
 ?>

構(gòu)造函數(shù)和析構(gòu)函數(shù)

每一個(gè)類都有兩個(gè)特殊的函數(shù),這兩個(gè)函數(shù)會(huì)自動(dòng)在兩個(gè)時(shí)刻調(diào)用挪蹭。

構(gòu)造函數(shù)

每次new一個(gè)新對(duì)象時(shí)亭饵,類中的構(gòu)造函數(shù)就自動(dòng)被調(diào)用了。

<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    public function __construct()
    {
        echo 'i am coming....';
    }

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        return $this->username; // $this代表當(dāng)前對(duì)象
    }


}

$p1 = new People();
var_dump($p1->username);
 ?>

注意:
構(gòu)造函數(shù)的參數(shù):在構(gòu)造函數(shù)中可以設(shè)置參數(shù)梁厉,如果設(shè)置了參數(shù)辜羊,那么在new時(shí)必須要把參數(shù)加上,如果不傳會(huì)報(bào)錯(cuò)懂算。


<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    public function __construct($username)
    {
        echo 'i am coming....';
    }

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        return $this->username; // $this代表當(dāng)前對(duì)象
    }


}

$p1 = new People();
var_dump($p1->username);
 ?>

構(gòu)造函數(shù)可以設(shè)置默認(rèn)值只冻。

<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    public function __construct($username = 'default')
    {
        echo 'i am coming....';
    }

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        return $this->username; // $this代表當(dāng)前對(duì)象
    }


}

$p1 = new People();
var_dump($p1->username);
 ?>

析構(gòu)函數(shù)

當(dāng)一個(gè)對(duì)象被刪除時(shí),被自動(dòng)調(diào)用的函數(shù)计技。


<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    public function __construct($username = '')
    {
        echo 'i am coming....';
    }

    // 注意:這里沒有加上 public 相當(dāng)于 public function getAge
    function getAge(){

    }

    public function getName()
    {
        return $this->username; // $this代表當(dāng)前對(duì)象
    }

    public function __destruct()
    {
        echo 'i am destory';
    }


}

$p1 = new People();

unset($p1);// 消耗對(duì)象

echo 'last';
 ?>

繼承-extends

一個(gè)類可以使用extends繼承自另一個(gè)類喜德,繼承之后就擁有了父類中的非私有的常量、屬性和方法垮媒,一個(gè)類只能有一個(gè)父類舍悯。

<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    public function __construct($username = '')
    {
        echo 'i am coming....';
    }

}

/**
 * Male類繼承People類
 */
class Male extends People
{

    public function getInfo()
    {
        echo 'i am male';
    }

}

 ?>

重寫

子類中可以定義一個(gè)一樣的東西就覆蓋了父類。


<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    public function __construct($username = '')
    {
        echo 'i am coming....';
    }

    public function getUserName()
    {
        return $this->username;
    }
}

/**
 * Male類繼承People類
 */
class Male extends People
{
    // 重寫
    public function getUserName()
    {
        echo 'i am getUserName';
    }


    public function getInfo()
    {
        echo 'i am male';
    }

}

 ?>

重載

PHP所提供的"重載"(overloading)是指動(dòng)態(tài)地"創(chuàng)建"類屬性和方法睡雇。是通過魔術(shù)方法(magic methods)來實(shí)現(xiàn)的萌衬。

當(dāng)調(diào)用當(dāng)前環(huán)境下未定義或不可見的類屬性或方法時(shí),重載方法會(huì)被調(diào)用它抱。

父類方法調(diào)用

子類中可以明確指定調(diào)用父類的方法:使用parent關(guān)鍵字


<?php 
/**
 * People類
 */
class People
{
    var $username = 'andy';
    var $age = 12;
    private $salary = 10000;

    public function __construct($username = '')
    {
        echo 'i am coming....';
    }

    public function getUserName()
    {
        return $this->username;
    }
}

/**
 * Male類繼承People類
 */
class Male extends People
{

    public function getInfo()
    {
        parent::getUserName();
        echo 'i am male';
    }

}

 ?>

繼承中的構(gòu)造函數(shù)

如果父類中有構(gòu)造函數(shù)秕豫,然后子類又有一個(gè)構(gòu)造函數(shù),就會(huì)導(dǎo)致子類的覆蓋父類的观蓄,導(dǎo)致父類的構(gòu)造函數(shù)無法執(zhí)行混移。

解決辦法:一般子類中如果寫了構(gòu)造函數(shù)那么必須先調(diào)用父類的構(gòu)造函數(shù)。


<?php 
/**
 * People類
 */
class People
{
    public $username = 'andy';
    private $salary = 10000;

    public function __construct($username)
    {
        $this->username = $username;
    }

    public function getUserName()
    {
        return $this->username;
    }
}

/**
 * Male類繼承People類
 */
class Male extends People
{

    public function __construct($username){
        parent::__construct($username);
    }

    public function getInfo()
    {
        return $this->username;
    }

}

$m = new Male('li xiaoming');
var_dump( $m->getInfo() );

 ?>

final關(guān)鍵字

可以把final放到類和方法的前面:代表這個(gè)類或者方法不能被繼承侮穿。加在類前面:這個(gè)類不能被繼承歌径。

<?php 
final Class A{

}

// 出錯(cuò)
Class B extends A{
    
}

 ?>

訪問控制

在類中可以使用public、protected和private來控制屬性和方法的訪問權(quán)限:

public

公開的:所有位置都可以直接訪問亲茅。

protected

受保護(hù)的:只有當(dāng)前類和子類中可以訪問回铛。

private

私有的:只有當(dāng)前類中可以訪問狗准。

static 靜態(tài)

在類中可以使用static定義一個(gè)靜態(tài)屬性和靜態(tài)方法。
普通屬性和靜態(tài)屬性的區(qū)別

  1. 語(yǔ)法區(qū)別
  2. 靜態(tài)變量屬于這個(gè)類茵肃,所以不需要new對(duì)象可以直接使用類名訪問
  3. 普通變量屬于一個(gè)具體對(duì)象腔长,每new出一個(gè)對(duì)象,里面都有一個(gè)這個(gè)屬性免姿,必須new出來的對(duì)象饼酿,所以需要先new一個(gè)對(duì)象才能使用

<?php 

/**
 * Static學(xué)習(xí)
 */
class Test
{
   public static $count = 0;
}

echo Test::$count;

?>

靜態(tài)屬性

靜態(tài)屬性可以被繼承榕酒,只屬于這個(gè)類胚膊,跟具體new出來的對(duì)象沒關(guān)系,可以直接使用類名來操作想鹰。


<?php 

/**
 * Static學(xué)習(xí)
 */
class Test
{
   public static $count = 0;
}

/**
 * B
 */
class B extends Test
{
    
}
echo B::$count;

?>

靜態(tài)方法

靜態(tài)方法屬于一個(gè)類不屬于任何對(duì)象紊婉, 所以不需要new可以直接調(diào)用辑舷。

<?php 

/**
 * Static學(xué)習(xí)
 */
class Test
{
   public static $count = 0;

   public static function getCount()
   {
        return 'count';
   }
}

echo Test::getCount();

?>

注意:
在靜態(tài)方法中不能訪問普通屬性喻犁。

<?php 

/**
 * Static學(xué)習(xí)
 */
class Test
{
   public static $count = 0;
   public $number = 12;

   public static function getCount()
   {
        return $this->number;
   }
}

echo Test::getCount();

?>

self

在類內(nèi)部如果要訪問自己的靜態(tài)屬性或者方法時(shí)可以使用self何缓。

<?php 

/**
 * Static學(xué)習(xí)
 */
class Test
{
   public static $count = 0;
   public $number = 12;

   public static function getCount()
   {
        return self::$count;
   }
}

echo Test::getCount();

?>

后期綁定谷婆,也叫作晚綁定

代碼

<?php 

class A{
    public function abc()
    {
        echo 'abc in A Class';
    }

    public function bcd()
    {
        $this->abc();
    }
}


class B extends A{
    public function abc()
    {
        echo 'abc in B Class';
    }
}
$b = new A();
$b->bcd();

// 1. 先定義一個(gè) A 纪挎,定義 abc
// 2. 在定義一個(gè) B,定義 abc
// 3. 讓B繼承A烤蜕,這個(gè)時(shí)候 B的 abc會(huì)覆蓋 A的abc
// 4. 在A里面在定義 bcd
// 5. 實(shí)例化 A類呐籽,調(diào)用 bcd,則輸出什么硼端?
// 6. 那么實(shí)例化 B類兔毙,調(diào)用 bcd肴裙,則輸出什么夕晓?

?>

總結(jié):$this是取決于誰(shuí)調(diào)用,是在真正運(yùn)行的時(shí)候才知道的。不是事先定義好的(在編譯的時(shí)候已經(jīng)固定了)宰译,將來看怎么運(yùn)行的沿侈,是屬于后面的才知道蛛淋,稱為綁定缀台。那么什么是早綁定呢脯丝?

后期靜態(tài)綁定

self-早綁定

self是早綁定的,self寫到哪個(gè)類里就代表哪個(gè)類,無論是哪個(gè)對(duì)象調(diào)用勇哗。


<?php 

class A{

    public static function abc()
    {
        echo 'abc in A Class';
    }

    public function bcd()
    {
        self::abc(); // 已經(jīng)固定毅厚,在編譯的時(shí)候就確定 self 代表A,無論是哪個(gè)類的對(duì)象調(diào)用刺啦,都是A染苛。
    }
}


class B extends A{
    public static function abc()
    {
        echo 'abc in B Class';
    }
}
$b = new B();
$b->bcd();

// 1. 先定義一個(gè) A 结执,定義 abc
// 2. 在定義一個(gè) B,定義 abc
// 3. 讓B繼承A,這個(gè)時(shí)候 B的 abc會(huì)覆蓋 A的abc
// 4. 在A里面在定義 bcd
// 5. 實(shí)例化 A類州刽,調(diào)用 bcd空执,則輸出什么?
// 5. 那么實(shí)例化 B類穗椅,調(diào)用 bcd辨绊,則輸出什么?

?>


static-晚綁定

為了給靜態(tài)方法也提供一個(gè)晚綁定的功能匹表,所以PHP從5.3開始出了一個(gè)static關(guān)鍵字可以用來晚綁定來調(diào)用一個(gè)靜態(tài)方法


<?php 

class A{

    public static function abc()
    {
        echo 'abc in A Class';
    }

    public function bcd()
    {
        static::abc(); // static 是靜態(tài)方法的晚綁定门坷,有運(yùn)行時(shí)候決定
    }
}


class B extends A{
    public static function abc()
    {
        echo 'abc in B Class';
    }
}
$b = new B();
$b->bcd();

// 1. 先定義一個(gè) A ,定義 abc
// 2. 在定義一個(gè) B袍镀,定義 abc
// 3. 讓B繼承A默蚌,這個(gè)時(shí)候 B的 abc會(huì)覆蓋 A的abc
// 4. 在A里面在定義 bcd
// 5. 實(shí)例化 A類,調(diào)用 bcd苇羡,則輸出什么绸吸?
// 5. 那么實(shí)例化 B類,調(diào)用 bcd设江,則輸出什么锦茁?

?>

parent-早綁定

如果要調(diào)用父類中的靜態(tài)方法


<?php 

class A{

    public static function abc()
    {
        echo 'abc in A Class';
    }

}


class B extends A{
    public static function abc()
    {
        echo 'abc in B Class';
    }

    public function bcd(){
        parent::abc(); // 調(diào)用父類的靜態(tài)方法,屬于早綁定
    }
}
$b = new B();
$b->bcd();


?>

總結(jié):

  1. self和parent是靜態(tài)綁定叉存,是早綁定码俩。
  2. $this和static是晚綁定 :主要要看是哪個(gè)對(duì)象調(diào)用的。

參數(shù)的類型約束

可以規(guī)定一個(gè)函數(shù)上的參數(shù)必須是某種類型的歼捏,目前只能做這四種的類型約束:類稿存、數(shù)組、接口或者callable瞳秽。


<?php 

class Test{

    public function init(A $a)
    {
        var_dump($a);
    }
}

class A{

}

$a = new A();
$t1 = new Test();
$t1->init($a);

 ?>

注意:
類約束時(shí)可以傳類和這個(gè)類子類的對(duì)象都可以瓣履,比如下面這個(gè)例子:要求傳一個(gè)Animal類的對(duì)象。但傳了一個(gè)Dog類的對(duì)象也可以寂诱,因?yàn)镈og是Animal的子類拂苹。

魔術(shù)方法

我們?cè)陬愔卸x好這些方法之后,在某一個(gè)特定時(shí)刻自動(dòng)被調(diào)用的方法。比如構(gòu)造函數(shù)是在new一個(gè)對(duì)象時(shí)被自動(dòng)調(diào)用瓢棒。


常見的模式方法

__get和__set

當(dāng)要讀取和設(shè)置一個(gè)對(duì)象中不存在的屬性時(shí)該方法就會(huì)被調(diào)用了浴韭。

類的自動(dòng)加載

PHP中提供了一個(gè)函數(shù)__autoload也是一個(gè)魔術(shù)方法,當(dāng)使用一個(gè)類時(shí)脯宿,如果這個(gè)類找不到那么這個(gè)方法就被調(diào)用念颈。

__autoload

<?php 

function __autoload($className)
{
    var_dump($className);
}

$a = new A();

 ?>

現(xiàn)在我們用一個(gè)類時(shí)必須先把這個(gè)類所在的PHP文件引入進(jìn)來這樣比較麻煩,是否可以讓PHP自動(dòng)加載我們需要使用的類连霉?
可以使用autoload實(shí)現(xiàn):

  1. 一個(gè)文件中只寫一個(gè)類
  2. 文件名和類名相同
  3. 定義一個(gè)autoload函數(shù)根據(jù)類名自動(dòng)加載相應(yīng)的類

<?php 

function __autoload($className)
{
    include $className . '.php'; // 完成類的載入
}

$a = new A();

 ?>

spl_autoload_register和spl_autoload_unregister

前面的__autoload很早以前就有比較舊榴芳,后來又提供了兩個(gè)函數(shù)可以提供更加載的自動(dòng)加載功能:
__autoload只能是這一個(gè)函數(shù),使用spl_autoload_register注冊(cè)多個(gè)自動(dòng)加載函數(shù)跺撼。

注意:
加載函數(shù)也可以是一個(gè)類中的一個(gè)方法窟感。

<?php 

/**
 * Loader加載器
 */
class Loader
{
    /**
     * Loader加載器
     */
    public static function load($className)
    {
        include $className . '.php';
    }
}

spl_autoload_register('Loader::load');

$a = new A();

 ?>

spl_autoload_unregister:刪除一個(gè)已經(jīng)注冊(cè)的函數(shù)。

抽象方法和抽象類-abstract

抽象類:只要類中有一個(gè)抽象類方法那么這個(gè)類必須定義成抽象類歉井。
抽象方法:先定義這個(gè)方法的名字和參數(shù)柿祈,但先不寫具體里面的代碼,這種抽象類必須被子類繼承并且重寫所有抽象類中的抽象方法然后才可以使用哩至。


<?php 

/**
 * Db類是抽象類
1. 里面存在一個(gè)抽象方法
2. 類的前面必須加上 abstract 
 */
abstract class Db
{
    abstract public function init();

}

/**
 * Mysql
 */
class Mysql extends Db
{
    public function init()
    {
        echo 'mysql init';
    }
}

$mysql = new Mysql();
$mysql->init();

 ?>

抽象語(yǔ)法:
1 . 如果一個(gè)方法前面加上abstract代表這是一個(gè)抽象的方法躏嚎,抽象方法不能有方法體,只有方法名菩貌。

  1. 如果一個(gè)類中有抽象方法卢佣,那么這個(gè)類就是抽象類(未完成的類),所以類前面要加上abstract箭阶。
  2. 抽象類不能直接實(shí)例對(duì)象虚茶,必須被繼承,子類只有重寫了所有父類中的抽象方法之后這個(gè)子類才能使用尾膊。
  3. 如果子類沒有重寫父類中所有的抽象方法媳危,那么這個(gè)子類也是抽象類。

接口

完全抽象的抽象類就是接口冈敛,類里全是抽象方法。

<?php 

/**
 * Db類里面的方法全部為抽象方法鸣皂,則一般定義為接口抓谴,同時(shí)去除 abstract關(guān)鍵字,該為 interface
 */
<?php 

/**
 * Db接口
 */
interface Db
{
    const PORT = 3306;
    public function init();

    public function open();

    public function read();

    public function write();

}

 ?>

使用interface定義接口寞缝,接口里面只有:

  1. 沒有方法體的方法
  2. 常量

接口是不能用的癌压,必須有一個(gè)類實(shí)現(xiàn)(implement)了這個(gè)接口,這個(gè)類才能使用荆陆。如果一個(gè)類要實(shí)現(xiàn)一個(gè)接口滩届,那么這個(gè)類中必須重寫接口中所有的方法。


<?php 

/**
 * Db接口
 */
interface Db
{
    const PORT = 3306;
    public function init();

    public function open();

    public function read();

    public function write();

}

/**
 * Mysql 實(shí)現(xiàn)Db接口
 */
class Mysql implements Db
{
    public function init()
    {
        
    }
    public function open()
    {
        
    }
    public function read()
    {
        
    }
    public function write()
    {
        
    }
}
 ?>

接口繼承

一個(gè)接口可以繼承另外一個(gè)接口被啼,然后在添加抽象方法帜消,等待其他類去實(shí)現(xiàn)棠枉。


<?php 

/**
 * Db接口
 */
interface Db
{
    const PORT = 3306;
    public function init();

    public function open();

    public function read();

    public function write();

}

/**
 * Mysql 繼承Db接口,增加了一個(gè)sql注入處理
 */
interface Mysql extends Db
{
    public function sqlInjectRemove();
}
 ?>

接口實(shí)現(xiàn)


<?php 

/**
 * Db接口
 */
interface Db
{
    const PORT = 3306;
    public function init();

    public function open();

    public function read();

    public function write();

}

/**
 * Mysql 實(shí)現(xiàn)Db接口
 */
class Mysql implements Db
{
    public function init()
    {
        
    }
    public function open()
    {
        
    }
    public function read()
    {
        
    }
    public function write()
    {
        
    }
}
 ?>

注意:
一個(gè)類可以同時(shí)實(shí)現(xiàn)多個(gè)接口泡挺。


<?php 

/**
 * Db接口
 */
interface Db
{
    const PORT = 3306;
    public function init();

    public function open();

    public function read();

    public function write();

}

interface SecretDb{
    // 過濾參數(shù)
    public function filterParams();
}

/**
 * Mysql 繼承Db接口辈讶,增加了一個(gè)sql注入處理
 */
class Mysql implements Db,SecretDb
{   
    // 實(shí)現(xiàn) SecretDb 接口
    public function filterParams(){

    }

    // 實(shí)現(xiàn) Db即可
     public function init()
    {
        
    }
    public function open()
    {
        
    }
    public function read()
    {
        
    }
    public function write()
    {
        
    }

}
 ?>

總結(jié):
PHP中的類是單繼承、多實(shí)現(xiàn)娄猫。

trait

trait是什么贱除?

trait 是比較類似的,可以有自己的屬性和方法媳溺,但是不能單獨(dú)被使用實(shí)例化月幌。主要用來擴(kuò)展另外一個(gè)類的功能,在一個(gè)類中需要使用use來引入trait里面的功能悬蔽。

定義

和類的編寫方式一致扯躺。只是將 class 關(guān)鍵字換為 trait。

使用trait

在類中使用use來?yè)碛衪rait里面所有的東西屯阀。

注意:
可以同時(shí)use多個(gè)trait缅帘。

trait方法的沖突

如果同時(shí)擁有的多個(gè)trait有同名的方法那么就沖突會(huì)報(bào)錯(cuò)。

trait屬性的沖突

如果trait里面定義了一個(gè)屬性那么類里面不能再定義同名屬性难衰,否則會(huì)出錯(cuò)钦无。
使用trait時(shí)可以使用as把沖突的名字起個(gè)別名。

使用trait組成trait

在一個(gè)trait里面盖袭,可以使用其他的trait失暂。

對(duì)象序列化

當(dāng)要把一個(gè)對(duì)象持久化,保存到數(shù)據(jù)庫(kù)鳄虱、文件等等時(shí)需要先序列化弟塞,轉(zhuǎn)化成字符串保存,取出來用時(shí)要先反序列化拙已,把字符串轉(zhuǎn)化回對(duì)象再使用决记。

  1. serialize:序列化
  2. unserialize:反序列化

匿名類

沒有名字的類。

匿名類

如果一個(gè)類只使用一次倍踪,那么可以不用定義這個(gè)類直接new一個(gè)匿名類即可系宫。


異常處理

什么是異常處理

異常處理是在面向?qū)ο笾行乱氲奶幚礤e(cuò)誤的一種方式。當(dāng)出錯(cuò)時(shí)程序throw一個(gè)Exception類的對(duì)象建车,然后在通過 try{代碼塊}catch(Exception){處理錯(cuò)誤信息}finally{ }來捕獲并處理錯(cuò)誤扩借。

在面向過程中我們每做一個(gè)操作都要根據(jù)返回值判斷這個(gè)操作是否成功了,一般都是如下的編寫處理方式:

<?php 

@$link = mysql_connect('127.0.0.1', 'root', 'admin');

if(!$link){
    exit('can not link mysql');
}else{
    $status = mysql_selectdb('test');
    if(!$status){
        exit('can not open test datatbase');
    }else{
        //....
    }
    
}

 ?>

面向?qū)ο笾刑峁┝艘环N新的報(bào)錯(cuò)(這個(gè)錯(cuò)誤一般被稱為異常)的語(yǔ)法:

<?php 

/**
 * File類缤至,主要用于文件的操作
 */
class File
{
    public $file;

    public function open($fileName)
    {
        throw new Exception('file can not open');
    }

    public function write()
    {
        throw new Exception('file can not write');
    }

    public function close()
    {
        //file close
        var_dump('file close');
    }
}

$file = new File();
try {

    $file->open('a.txt');
    
} catch (Exception $e) {
    var_dump($e->getMessage()); // 獲取錯(cuò)誤信息
    var_dump($e->getCode()); // 獲取錯(cuò)誤代碼
    var_dump($e->getFile()); // 獲取出錯(cuò)文件信息
    var_dump($e->getLine()); // 獲取出錯(cuò)信息所在的行號(hào)
}


注意:
異常處理是新的處理錯(cuò)誤的語(yǔ)法:只有面向?qū)ο蟮臇|西支持潮罪。

PHP中內(nèi)置的Exception異常類

出錯(cuò)時(shí)所有throw的對(duì)象都這個(gè)類或者這個(gè)類的子類。


異常類

我們可以寫自己的異常類擴(kuò)展這個(gè)PHP中自帶的Exception異常類。


<?php

/**
 * Connect
 */
class ConnectException extends Exception
{
   protected $messsage = '連接數(shù)據(jù)庫(kù)失敗';
}


class QueryException extends Exception
{
   protected $messsage = '執(zhí)行SQL語(yǔ)句失敗';
}


/**
 * Goods模型
 */
class GoodsModel
{
    public function open()
    {
        if(!mysql_connect('127.0.0.1', 'root', 'admin88')){
            throw new ConnectException();
        }

        if(!mysql_query('select * from test2')){
            throw new QueryException();
        }
    }
}


?>

拋出錯(cuò)誤:throw

當(dāng)失敗時(shí)就throw一個(gè)Exception類或者子類的對(duì)象嫉到,throw之后的代碼就不再執(zhí)行了沃暗。


<?php 

class GoodsModel
{
    public function open()
    {

        var_dump('first');
        throw new Exception('連接數(shù)據(jù)庫(kù)失敗');
        var_dump('second'); // 這里的代碼不在執(zhí)行

    }
}

$goodsModel = new GoodsModel();
try {

    $goodsModel->open();
    
} catch (Exception $e) {
    var_dump($e->getMessage());
}


 ?>

捕獲:try...catch[...catch....]

當(dāng)發(fā)生異常的時(shí)候,然后使用catch捕獲異常屯碴。


<?php 

class GoodsModel
{
    public function open()
    {

        var_dump('first');
        throw new Exception('連接數(shù)據(jù)庫(kù)失敗');
        var_dump('second'); // 這里的代碼不在執(zhí)行

    }
}

$goodsModel = new GoodsModel();
try {

    $goodsModel->open();
    
} catch (Exception $e) {
    var_dump($e->getMessage());
}


 ?>

一定會(huì)執(zhí)行:finally

finally代表是最終的意思描睦,最后的代碼一定會(huì)執(zhí)行,例如我們打開一個(gè)文件后导而,無論是讀寫是否正常忱叭,最后一定都是需要關(guān)閉文件的。


<?php 

/**
 * File類今艺,主要用于文件的操作
 */
class File
{
    public $file;

    public function open($fileName)
    {
        throw new Exception('file can not open');
    }

    public function write()
    {
        throw new Exception('file can not write');
    }

    public function close()
    {
        //file close
        var_dump('file close');
    }
}

$file = new File();
try {

    $file->open('a.txt');
    
} catch (Exception $e) {
    var_dump($e->getMessage());
} finally{
    
    $file->close();
    
}


相關(guān)資料

面向?qū)ο髮n}
菜鳥教程-面向?qū)ο?/a>

  • 序言:七十年代末韵丑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子虚缎,更是在濱河造成了極大的恐慌撵彻,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件实牡,死亡現(xiàn)場(chǎng)離奇詭異陌僵,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)创坞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門碗短,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人题涨,你說我怎么就攤上這事偎谁。” “怎么了纲堵?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵巡雨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我席函,道長(zhǎng)铐望,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任茂附,我火速辦了婚禮蝌以,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘何之。我一直安慰自己,他們只是感情好咽筋,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布溶推。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蒜危。 梳的紋絲不亂的頭發(fā)上虱痕,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音辐赞,去河邊找鬼部翘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛响委,可吹牛的內(nèi)容都是我干的新思。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼赘风,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼夹囚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起邀窃,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤荸哟,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后瞬捕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鞍历,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年肪虎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了劣砍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡笋轨,死狀恐怖秆剪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情爵政,我是刑警寧澤仅讽,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站钾挟,受9級(jí)特大地震影響洁灵,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掺出,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一徽千、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汤锨,春花似錦双抽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)铐维。三九已至,卻和暖如春慎菲,著一層夾襖步出監(jiān)牢的瞬間嫁蛇,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工露该, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留睬棚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓解幼,卻偏偏與公主長(zhǎng)得像抑党,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子书幕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容