您好,登錄后才能下訂單哦!
這篇文章主要介紹“如何理解PHP面向?qū)ο蟪绦蛟O(shè)計(jì)抽象類、對象接口、instanceof和契約式編程”,在日常操作中,相信很多人在如何理解PHP面向?qū)ο蟪绦蛟O(shè)計(jì)抽象類、對象接口、instanceof和契約式編程問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何理解PHP面向?qū)ο蟪绦蛟O(shè)計(jì)抽象類、對象接口、instanceof和契約式編程”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
1、PHP中的抽象類
PHP 5 支持抽象類和抽象方法。定義為抽象的類不能被實(shí)例化。任何一個(gè)類,如果它里面至少有一個(gè)方法是被聲明為抽象的,那么這個(gè)類就必須被聲明為抽象的。被定義為抽象的方法只是聲明了其調(diào)用方式(參數(shù)),不能定義其具體的功能實(shí)現(xiàn)。在類的聲明中使用 abstract 修飾符可以將某個(gè)類聲明為抽象的。
可以這樣理解,抽象類作為一個(gè)基類,它把特定的細(xì)節(jié)留給繼承者來實(shí)現(xiàn)。通過抽象概念,可以在開發(fā)項(xiàng)目中創(chuàng)建擴(kuò)展性很好的架構(gòu)。
復(fù)制代碼 代碼如下:
abstract class AbstractClass
{
code...
}
1.1、抽象方法
使用 abstract 關(guān)鍵字定義抽象方法。抽象方法只保留方法原型(方法的定義中剔除了方法體之后的簽名),它包括存取級別、函數(shù)關(guān)鍵字、函數(shù)名稱和參數(shù)。他不包含({})或者括號內(nèi)部的任何代碼。例如下面的代碼就是一個(gè)抽象方法定義:
復(fù)制代碼 代碼如下:
abstract public function prototypeName($protoParam);
繼承一個(gè)抽象類的時(shí)候,子類必須定義父類中的所有抽象方法;另外,這些方法的訪問控制必須和父類中一樣(或者更為寬松)。此外方法的調(diào)用方式必須匹配,即類型和所需參數(shù)數(shù)量必須一致。
1.2、關(guān)于抽象類
某個(gè)類只要包含至少一個(gè)抽象方法就必須聲明為抽象類
聲明為抽象的方法,在實(shí)現(xiàn)的時(shí)候必須包含相同的或者更低的訪問級別。
不能使用 new 關(guān)鍵字創(chuàng)建抽象類的實(shí)例。
被聲明為抽象的方法不能包含函數(shù)體。
如果將擴(kuò)展的類也聲明為抽象類,在擴(kuò)展抽象類時(shí),可以不用實(shí)現(xiàn)所有的抽象方法。(如果某個(gè)類從抽象類繼承,當(dāng)它沒有實(shí)現(xiàn)基類中所聲明的所有抽象方法時(shí),它就必須也被聲明為抽象的。)
1.3、使用抽象類
復(fù)制代碼 代碼如下:
<?php
abstract class Car
{
abstract function getMaxSpeend();
}
class Roadster extends Car
{
public $Speend;
public function SetSpeend($speend = 0)
{
$this->Speend = $speend;
}
public function getMaxSpeend()
{
return $this->Speend;
}
}
class Street
{
public $Cars ;
public $SpeendLimit ;
function __construct( $speendLimit = 200)
{
$this -> SpeendLimit = $speendLimit;
$this -> Cars = array();
}
protected function IsStreetLegal($car)
{
if ($car->getMaxSpeend() < $this -> SpeendLimit)
{
return true;
}
else
{
return false;
}
}
public function AddCar($car)
{
if($this->IsStreetLegal($car))
{
echo 'The Car was allowed on the road.';
$this->Cars[] = $car;
}
else
{
echo 'The Car is too fast and was not allowed on the road.';
}
}
}
$Porsche911 = new Roadster();
$Porsche911->SetSpeend(340);
$FuWaiStreet = new Street(80);
$FuWaiStreet->AddCar($Porsche911);
/**
*
* @result
*
* The Car is too fast and was not allowed on the road.[Finished in 0.1s]
*
*/
?>
2.對象接口
使用接口(interface),可以指定某個(gè)類必須實(shí)現(xiàn)哪些方法,但不需要定義這些方法的具體內(nèi)容。
接口是通過 interface 關(guān)鍵字來定義的,就像定義一個(gè)標(biāo)準(zhǔn)的類一樣,但其中定義所有的方法都是空的。
接口中定義的所有方法都必須是公有,這是接口的特性。
接口是一種類似于類的結(jié)構(gòu),可用于聲明實(shí)現(xiàn)類所必須聲明的方法。例如,接口通常用來聲明API,而不用定義如何實(shí)現(xiàn)這個(gè)API。
大多數(shù)開發(fā)人員選擇在接口名稱前加上大寫字母I作為前綴,以便在代碼和生成的文檔中將其與類區(qū)別開來。
2.1接口實(shí)現(xiàn)(implements)
要實(shí)現(xiàn)一個(gè)接口,使用 implements 操作符(繼承抽象類需要使用 extends 關(guān)鍵字不同),類中必須實(shí)現(xiàn)接口中定義的所有方法,否則會報(bào)一個(gè)致命錯(cuò)誤。類可以實(shí)現(xiàn)多個(gè)接口,用逗號來分隔多個(gè)接口的名稱。
實(shí)現(xiàn)多個(gè)接口時(shí),接口中的方法不能有重名。
接口也可以繼承,通過使用 extends 操作符。
類要實(shí)現(xiàn)接口,必須使用和接口中所定義的方法完全一致的方式。否則會導(dǎo)致致命錯(cuò)誤。
接口中也可以定義常量。接口常量和類常量的使用完全相同,但是不能被子類或子接口所覆蓋。
2.2使用接口的案例
復(fù)制代碼 代碼如下:
<?php
abstract class Car
{
abstract function SetSpeend($speend = 0);
}
interface ISpeendInfo
{
function GetMaxSpeend();
}
class Roadster extends Car implements ISpeendInfo
{
public $Speend;
public function SetSpeend($speend = 0)
{
$this->Speend = $speend;
}
public function getMaxSpeend()
{
return $this->Speend;
}
}
class Street
{
public $Cars ;
public $SpeendLimit ;
function __construct( $speendLimit = 200)
{
$this -> SpeendLimit = $speendLimit;
$this -> Cars = array();
}
protected function IsStreetLegal($car)
{
if ($car->getMaxSpeend() < $this -> SpeendLimit)
{
return true;
}
else
{
return false;
}
}
public function AddCar($car)
{
if($this->IsStreetLegal($car))
{
echo 'The Car was allowed on the road.';
$this->Cars[] = $car;
}
else
{
echo 'The Car is too fast and was not allowed on the road.';
}
}
}
$Porsche911 = new Roadster();
$Porsche911->SetSpeend(340);
$FuWaiStreet = new Street(80);
$FuWaiStreet->AddCar($Porsche911);
/**
*
* @result
*
* The Car is too fast and was not allowed on the road.[Finished in 0.1s]
*
*/
?>
3、類型運(yùn)算符 instanceof
instanceof 運(yùn)算符是 PHP5 中的一個(gè)比較操作符。他接受左右兩邊的參數(shù),并返回一個(gè)boolean值。
確定一個(gè) PHP 變量是否屬于某個(gè)一類 CLASS 的實(shí)例
檢查對象是不是從某個(gè)類型繼承
檢查對象是否屬于某個(gè)類的實(shí)例
確定一個(gè)變量是不是實(shí)現(xiàn)了某個(gè)接口的對象的實(shí)例
復(fù)制代碼 代碼如下:
echo $Porsche911 instanceof Car;
//result:1
echo $Porsche911 instanceof ISpeendInfo;
//result:1
4.契約式編程
契約式設(shè)計(jì)或者Design by Contract (DbC)是一種設(shè)計(jì)計(jì)算機(jī)軟件的方法。這種方法要求軟件設(shè)計(jì)者為軟件組件定義正式的,精確的并且可驗(yàn)證的接口,這樣,為傳統(tǒng)的抽象數(shù)據(jù)類型又增加了先驗(yàn)條件、后驗(yàn)條件和不變式。這種方法的名字里用到的“契約”或者說“契約”是一種比喻,因?yàn)樗蜕虡I(yè)契約的情況有點(diǎn)類似。
在編寫類之前實(shí)現(xiàn)聲明接口的一種編程實(shí)踐。這種方法在保證類的封裝性方面非常有用。使用契約式編程技術(shù),我們可以在創(chuàng)建應(yīng)用程序之前定義出視圖實(shí)現(xiàn)的功能,這和建筑師在修建大樓之前先畫好藍(lán)圖的做法非常相似。
5.總結(jié)
抽象類是使用 abstract 關(guān)鍵字聲明的類。通過將某個(gè)類標(biāo)記為抽象類,我們可以推遲實(shí)現(xiàn)所聲明的方法。要將某個(gè)方法聲明為抽象方法,只要去掉包含所有大括號的方法實(shí)體,將方法聲明的代碼行用分號結(jié)束即可。
抽象類不能直接實(shí)例化,他們必須被繼承。
如果某個(gè)類從抽象類繼承,當(dāng)它沒有實(shí)現(xiàn)基類中所聲明的所有抽象方法時(shí),它就必須也被聲明為抽象的。
在接口中,我們可以聲明沒有方法體的方法原型,這點(diǎn)與抽象類很相似。他們之間的區(qū)別在于,接口不能聲明任何具有方法體的方法;并且他們使用的語法也不一樣。為了將揭開規(guī)則強(qiáng)制加到某個(gè)類上,我們需要使用implements關(guān)鍵字,而不是extends關(guān)鍵字。
有些情況下我們需要確定某個(gè)類是否是特定類的類型,或者是否實(shí)現(xiàn)了特定的接口。 instanceof 分成適合完成這個(gè)任務(wù)。instanceof 檢查三件事情:實(shí)例是否是某個(gè)特定的類型,實(shí)例是否從某個(gè)特定的類型繼承,實(shí)例或者他的任何祖先類是否實(shí)現(xiàn)類特定的接口。
某些語言具有從多個(gè)類繼承的能力,這稱為多重繼承。PHP不支持多重繼承。想法,他提供了為一個(gè)類聲明多個(gè)接口的功能。
接口在聲明類必須遵循的規(guī)則時(shí)非常有用。契約式編程技術(shù)使用這一功能來增強(qiáng)封裝性,優(yōu)化工作流。
到此,關(guān)于“如何理解PHP面向?qū)ο蟪绦蛟O(shè)計(jì)抽象類、對象接口、instanceof和契約式編程”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。