18.PHP面向?qū)ο?高級(jí)實(shí)踐

繼承

運(yùn)動(dòng)員 所擁有的的屬性和方法:
姓名 身高 體重 所在球隊(duì) 球員號(hào)碼 講話 行走 扣籃 運(yùn)球

演員 所擁有的的屬性和方法:
姓名 身高 體重 藝名 所屬公司 講話 行走 唱歌 演戲

我們可以把公用的成員提取出來(lái),他們擁有部分相同的屬性和方法 因?yàn)樗麄兌际侨祟悺?/p>

繼承的好處

  • 父類里面定義的成員可以不用再子類中重復(fù)定義,節(jié)約了變成的時(shí)間和代價(jià)

  • 同一父類的子類擁有相同的父類定義類的成員,因此外部調(diào)用他們的時(shí)候可以一視同仁

  • 子類可以修改和調(diào)整父類定義的類成員,我們稱之為重寫,一旦類修改了,就按照子類修改之后的功能執(zhí)行

在php中可以用extends關(guān)鍵字來(lái)標(biāo)示類的繼承,后面跟父類的類名,extends后面只能跟一個(gè)類的類名,這就是php中的單繼承原則

訪問(wèn)控制

關(guān)鍵字 特點(diǎn)
public 公有類成員 可以在任何地方被訪問(wèn)
protected 受保護(hù)的類成員,可以被其自身以及子類訪問(wèn)
private 私有的類成員,只能被自身訪問(wèn)

靜態(tài)成員,static

好處

使類的靜態(tài)成員特性就可以共用屬性。

定義

靜態(tài)屬性定義時(shí)在訪問(wèn)控制關(guān)鍵字后面添加static關(guān)鍵字即可

調(diào)用

在類定義中使用靜態(tài)成員的時(shí)候,用self或者static關(guān)鍵字緊跟著::操作符調(diào)用。

self與static的差異
其差異體現(xiàn)在繼承時(shí):slef永遠(yuǎn)綁定的是代碼所在類;static調(diào)用時(shí)確定哪個(gè)類。常用static,更加符合常規(guī)邏輯。

定義外部訪問(wèn)靜態(tài)屬性,我們可以用類名加::操作符的方法來(lái)訪問(wèn)類的靜態(tài)成員;使用parent關(guān)鍵字技能訪問(wèn)父類的靜態(tài)成員。

靜態(tài)方法里面只能訪問(wèn)靜態(tài)屬性

訪問(wèn) ClassName::method() 或者 ClassName::$property

如何使用靜態(tài)成員

例如:老師要統(tǒng)計(jì)學(xué)生的數(shù)量,問(wèn)題是,如果所有的操作,嚴(yán)格按照面向?qū)ο蟮乃枷肴プ?,意味著?huì)出現(xiàn)無(wú)數(shù)個(gè)對(duì)象,其中很多,僅僅為了輔助完成個(gè)別功能,也要定義類,實(shí)例化對(duì)象, 萬(wàn)物萬(wàn)事都是對(duì)象,難道真的要定義萬(wàn)事萬(wàn)物?

此時(shí),通過(guò)在某些類上增加靜態(tài)成員的方式,完成某類特定的操作。

總結(jié):當(dāng)使用靜態(tài)成員時(shí),認(rèn)為被所有的當(dāng)前類對(duì)象所共享的數(shù)據(jù)和操作,應(yīng)該聲明成靜態(tài)的。被對(duì)象所獨(dú)有的數(shù)據(jù)和操作,應(yīng)該聲明成為非靜態(tài)的。

語(yǔ)法細(xì)節(jié)

無(wú)論采用對(duì)象還是類,都可以調(diào)用靜態(tài)、非靜態(tài)方法。但是涉及到語(yǔ)法嚴(yán)謹(jǐn)規(guī)范化。

類常量

常量一旦定義,不能修改,選擇用常量的原因:之一,語(yǔ)法層面保證,數(shù)據(jù)不會(huì)被修改;之二,將特定的數(shù)據(jù)語(yǔ)義化,得到計(jì)算快,同時(shí)表述有邏輯含義。

定義常量

如果需要類,擁有某個(gè)不需要變化的數(shù)據(jù),則可以通過(guò)定義類常量完成。定義通過(guò)const關(guān)鍵字,執(zhí)行名字和值,不需要訪問(wèn)修飾。

使用常量

通過(guò)::訪問(wèn)

設(shè)計(jì)相關(guān)

設(shè)計(jì)層面,當(dāng)需要完成某種約束規(guī)范時(shí),怎么去實(shí)現(xiàn)?

抽象 abstract

通過(guò)關(guān)鍵字abstract,限制類、方法。稱之為抽象類、抽象方法

抽象類

限制之后,該類就不能用于實(shí)例化對(duì)象。

例如,在設(shè)計(jì)商品管理系統(tǒng)的時(shí)候,認(rèn)為所有的商品(book,phone)應(yīng)該都是某種類型的商品的實(shí)例,而不是goods對(duì)象,goods類僅僅是為了提供所有類型商品的公共屬性和操作。如果滿足設(shè)計(jì)需求,語(yǔ)法上可將goods定義為抽象,從而保證不會(huì)被實(shí)例化。

其作用是:語(yǔ)法層面的限制。

抽象方法

僅僅包含了方法的聲明(方法名和形參列表),沒(méi)有方法的實(shí)現(xiàn)(方法體),稱之為抽象方法。

使用抽象方法的原因:需要限制子類,一定要存在,但是實(shí)現(xiàn)可以是不同的方法。例如任何類型的商品,都有獲取商品名稱的能力(方法),不同類型的商品獲取的方式不一樣。

終極 final

final可以用來(lái)修飾限制類、方法,也稱之為終極類、終極方法。

final類

final修飾類導(dǎo)致類不能被繼承使用。一個(gè)fianl類僅僅用來(lái)被實(shí)例化。

為什么要設(shè)計(jì)為final類呢?

設(shè)計(jì)層面,類達(dá)到某個(gè)級(jí)別的時(shí)候,就不能再繼承拓展了。

final方法

final修飾方法導(dǎo)致方法不能被子類重寫。

作用在于:為了保證所有的子類中實(shí)現(xiàn)完全一致的方法,才會(huì)將父類的方法聲明為終極方法。

例如:價(jià)格是所有商品統(tǒng)一計(jì)算的,可以將價(jià)格獲取定義在good類中,并聲明終極方法,此時(shí)所有的子類使用的計(jì)算價(jià)格的方法都是統(tǒng)一的。

接口 interface

封裝性:隱藏內(nèi)部實(shí)現(xiàn),僅僅開(kāi)放外部接口,語(yǔ)法上,公共的方法就是外部接口。

接口實(shí)現(xiàn)技術(shù):用來(lái)約束(限制)某個(gè)類(對(duì)象)應(yīng)該具有滿足公共方法(接口)列表的。

例如:作為一個(gè)usb設(shè)備廠商,設(shè)計(jì)程序。要求所有的設(shè)備都滿足某個(gè)操作規(guī)范,該規(guī)范在面向?qū)ο笤O(shè)計(jì)時(shí)就可以設(shè)計(jì)成技術(shù)結(jié)構(gòu)。

定義

關(guān)鍵字interface進(jìn)行定義,接口結(jié)構(gòu)中,僅僅存在公共的抽象方法。接口的目的是定義標(biāo)準(zhǔn)化操作規(guī)范,而不去實(shí)現(xiàn),由采用該接口的實(shí)體實(shí)現(xiàn)。

實(shí)現(xiàn)

關(guān)鍵字implements進(jìn)行實(shí)現(xiàn)接口。一個(gè)類可以實(shí)現(xiàn)多個(gè)接口,用,連接起來(lái)。

接口和抽象類的差異
接口:制作標(biāo)準(zhǔn)化,主要目的是標(biāo)準(zhǔn)化時(shí)用接口。
抽象類:在普通類的基礎(chǔ)上,增加了抽象方法。為子類提供公共成員的同時(shí),額外的限定子類的某些成員。

語(yǔ)法上:
接口中的抽象方法,僅僅能是公共的。
抽象類中的抽象方法,可以是保護(hù)的和公共的。

設(shè)計(jì)模式

想法先行,語(yǔ)法后行

單例|單例模式

單個(gè)實(shí)例,單個(gè)對(duì)象,語(yǔ)法上一個(gè)類可以實(shí)例化無(wú)數(shù)個(gè)對(duì)象。

  • 設(shè)計(jì)思想:如果一個(gè)類的一個(gè)對(duì)象就可以完成所有的功能
    例如:通常的項(xiàng)目中,只需要操作一個(gè)數(shù)據(jù)庫(kù)服務(wù)器,完成所有的功能。因此僅僅需要一個(gè)數(shù)據(jù)庫(kù)操作對(duì)象即可。

既然存在一個(gè)對(duì)象可以完成功能的對(duì)象,就需要在語(yǔ)法層面上,限制該類去得到多個(gè)對(duì)象,只能得到一個(gè)對(duì)象,目的為了節(jié)約對(duì)象成本,這種設(shè)計(jì),就被成為單例設(shè)計(jì)。

設(shè)計(jì)思路

  1. 私有化構(gòu)造方法
    限制在類外實(shí)例化對(duì)象,結(jié)果不能實(shí)例化對(duì)象,如何實(shí)例化對(duì)象?
    如果可以在類內(nèi)調(diào)用該構(gòu)造方法,就可以完成實(shí)例化工作了。

  2. 靜態(tài)的公共方法
    在沒(méi)有對(duì)象前,可以使用類調(diào)用靜態(tài)方法的方式。

  3. 靜態(tài)的私有方法
    完善公共靜態(tài)方法的業(yè)務(wù)邏輯,保證即使多次調(diào)用也只能得到一個(gè)對(duì)象
    核心在于,第一次可以將對(duì)象存儲(chǔ)起來(lái),第二次調(diào)取對(duì)。

  4. 私有化克隆方法
    禁止被克隆。

class A{
    //三私一公
    private static $class;
    private function __construct(){
    }
    private function __clone(){
    }
    public static function newClass(){
        if(!isset(static::$class)){
            static::$class = new A();
        }
        return static::$class;
    }
}

單例的另一種體現(xiàn)形式

function getOne(){
    static $class = null;
    if(!isset($class)){
        $class = new A();
    }
    return $class;
}

劣勢(shì):并沒(méi)有從根本上解決單例問(wèn)題,仍然可以new出來(lái)。
優(yōu)勢(shì):靈活,不需要去更改類本身的結(jié)構(gòu),可以做到同時(shí)適應(yīng)多個(gè)類。

所以實(shí)際開(kāi)發(fā)中:
如果要嚴(yán)格限制單例效果,使用三私一公單例模式,如果僅僅想實(shí)現(xiàn)單例效果,就使用類外的實(shí)現(xiàn)

如果想實(shí)現(xiàn)其他類的單例,可以傳參數(shù)

function getOne($classname){
    static $classlist = array();
    if(!isset($classlist[$classname])){
        $classlist[$classname] = new $classname();
    }
    return $classlist[$classname];
}
工廠模式

從類的功能上講,如果某個(gè)類的主要功能,用來(lái)生產(chǎn)其他類的對(duì)象,這樣的類,稱之為工廠類

工廠模式
class Factory{
    //生產(chǎn)線
    public static function getClass($class){
        static $classList = array();
        if(!isset($classList[$class])){
           $classList[$class] = new $class();
        }
        return $classList[$class];
    }
}

魔術(shù)方法

  • __tostring()
    echo $obj;//需要快速展示某個(gè)對(duì)象的摘要信息時(shí)會(huì)使用該方法。

  • __invoke($params)
    當(dāng)對(duì)象被當(dāng)成方法調(diào)用時(shí),這個(gè)方法會(huì)被自動(dòng)調(diào)用
    $obj();

  • __call($name,$params)
    當(dāng)對(duì)象訪問(wèn)不存在的方法名稱時(shí),__call方法會(huì)被自動(dòng)調(diào)用
    這個(gè)方法的參數(shù)第一個(gè)就是調(diào)用的方法名稱,第二個(gè)參數(shù)是方法調(diào)用的參數(shù)組成的數(shù)組

  • __callStatic()
    當(dāng)對(duì)象訪問(wèn)不存在的靜態(tài)方法名稱時(shí),__callStatic方法會(huì)被自動(dòng)調(diào)用
    這兩個(gè)方法在php里面也被成為方法的重載

  • __get($name)
    讀取不可訪問(wèn)屬性的值時(shí),會(huì)被調(diào)用

  • __set($name,$value)
    在給不可訪問(wèn)屬性賦值時(shí),會(huì)被調(diào)用

  • __isset($name)
    當(dāng)對(duì)不可訪問(wèn)屬性調(diào)用isset()或empty()時(shí),__isset()會(huì)被調(diào)用

  • __unset($name)
    當(dāng)對(duì)不可訪問(wèn)屬性調(diào)用時(shí),會(huì)被調(diào)用

  • __clone()
    $obj1 = $obj2 址傳遞 clone實(shí)現(xiàn)復(fù)制

相關(guān)函數(shù)

  • class_exists(類名)

  • method_exists(對(duì)象,方法名)

  • property_exists(對(duì)象,屬性名)

  • interface_exists(接口名)

  • get_class(對(duì)象)

  • get_called_class()得到調(diào)用該方法的類

  • get_parent_class(類名)得到類的父類

  • is_object()判斷是否是對(duì)象

  • is_a(對(duì)象,類名) instanceof判斷是否是某個(gè)類的實(shí)例

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容