繼承
運(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ì)思路
私有化構(gòu)造方法
限制在類外實(shí)例化對(duì)象,結(jié)果不能實(shí)例化對(duì)象,如何實(shí)例化對(duì)象?
如果可以在類內(nèi)調(diào)用該構(gòu)造方法,就可以完成實(shí)例化工作了。靜態(tài)的公共方法
在沒(méi)有對(duì)象前,可以使用類調(diào)用靜態(tài)方法的方式。靜態(tài)的私有方法
完善公共靜態(tài)方法的業(yè)務(wù)邏輯,保證即使多次調(diào)用也只能得到一個(gè)對(duì)象
核心在于,第一次可以將對(duì)象存儲(chǔ)起來(lái),第二次調(diào)取對(duì)。私有化克隆方法
禁止被克隆。
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í)例