溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

抽象類與接口的區(qū)別是什么

發(fā)布時(shí)間:2021-08-05 16:30:38 來(lái)源:億速云 閱讀:166 作者:Leah 欄目:編程語(yǔ)言

抽象類與接口的區(qū)別是什么,相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

抽象類

定義為抽象的類不能被實(shí)例化。

任何一個(gè)類,如果它里面至少有一個(gè)方法是被聲明為抽象的,那么這個(gè)類就必須被聲明為抽象的。

被定義為抽象的方法只是聲明了其調(diào)用方式(參數(shù)),不能定義其具體的功能實(shí)現(xiàn)。

繼承一個(gè)抽象類的時(shí)候,子類必須定義父類中的所有抽象方法,這些方法的訪問(wèn)控制必須和父類中一樣(或者更為寬松)。

語(yǔ)法

<?phpabstract class AbstractClass{//抽象方法 -- 強(qiáng)制要求子類定義這些方法// 我們的抽象方法僅需要定義需要的參數(shù)abstract protected function getValue();abstract protected function prefixValue($prefix);abstract protected function prefixName($name);//普通方法(非抽象)public function printOut(){print $this->getValue() . "\n";}}//子類繼承抽象類class ConcreteClass1 extends AbstractClass{protected function getValue() {return "ConcreteClass1";}//訪問(wèn)權(quán)限可以比父類更寬松或同權(quán)限public function prefixValue($prefix) {return "{$prefix}ConcreteClass1";}// 我們的子類可以定義父類簽名中不存在的可選參數(shù)public function prefixName($name, $separator = ".") {if ($name == "Pacman") {$prefix = "Mr";} elseif ($name == "Pacwoman") {$prefix = "Mrs";} else {$prefix = "";}return "{$prefix}{$separator} {$name}";}}$class1 = new ConcreteClass1;$class1->printOut();echo $class1->prefixValue('FOO_') ."\n";echo $class1->prefixName("Pacman"), "\n";//以上例程會(huì)輸出://ConcreteClass1 //FOO_ConcreteClass1//Mr. Pacman

接口(對(duì)象接口)

使用接口 (interface) 關(guān)鍵字,可以指定某個(gè)類必須實(shí)現(xiàn)哪些方法,但不需要定義這些方法的具體內(nèi)容,就像定義一個(gè)標(biāo)準(zhǔn)的類一樣,但其中定義所有的方法都是空的。

接口中定義的所有方法都必須是公有,這是接口的特性。

在接口中定義一個(gè)構(gòu)造方法是被允許的。在有些場(chǎng)景下這可能會(huì)很有用,例如用于工廠模式時(shí)。

接口中也可以定義常量。接口常量和類常量的使用完全相同,但是不能被子類或子接口所覆蓋。

要實(shí)現(xiàn)一個(gè)接口,使用 implements 操作符。類中必須實(shí)現(xiàn)接口中定義的所有方法,否則會(huì)報(bào)一個(gè)致命錯(cuò)誤。

類可以實(shí)現(xiàn)多個(gè)接口,用逗號(hào)來(lái)分隔多個(gè)接口的名稱。(注意:在 PHP 5.3.9 之前,實(shí)現(xiàn)多個(gè)接口時(shí),接口中的方法不能有重名,因?yàn)檫@可能會(huì)有歧義。在最近的 PHP 版本中,只要這些重名的方法簽名相同,這種行為就是允許的。)

接口也可以繼承,通過(guò)使用 extends 操作符。

類要實(shí)現(xiàn)接口,必須使用和接口中所定義的方法完全一致的方式。否則會(huì)導(dǎo)致致命錯(cuò)誤。

語(yǔ)法

#實(shí)現(xiàn)接口
<?php// 聲明一個(gè)'iTemplate'接口interface iTemplate{public function setVariable($name, $var);public function getHtml($template);}// 實(shí)現(xiàn)接口// 下面的寫法是正確的class Template implements iTemplate{private $vars = array();
  public function setVariable($name, $var){$this->vars[$name] = $var;}
  public function getHtml($template){foreach($this->vars as $name => $value) {$template = str_replace('{' . $name . '}', $value, $template);}
 return $template;}}// 下面的寫法是錯(cuò)誤的,會(huì)報(bào)錯(cuò),因?yàn)闆](méi)有實(shí)現(xiàn) getHtml():// Fatal error: Class BadTemplate contains 1 abstract methods// and must therefore be declared abstract (iTemplate::getHtml)class BadTemplate implements iTemplate{private $vars = array();
  public function setVariable($name, $var){$this->vars[$name] = $var;}}
#可拓充的接口
<?phpinterface a{public function foo();}interface b extends a{public function baz(Baz $baz);}// 正確寫法class c implements b{public function foo(){}public function baz(Baz $baz){}}// 錯(cuò)誤寫法會(huì)導(dǎo)致一個(gè)致命錯(cuò)誤class d implements b{public function foo(){}public function baz(Foo $foo){}}
#繼承多個(gè)接口
<?phpinterface a{public function foo();}interface b{public function bar();}interface c extends a, b{public function baz();}class d implements c{public function foo(){}public function bar(){}public function baz(){}}
#使用接口常量
<?phpinterface a{const b = 'Interface constant';}// 輸出接口常量echo a::b;// 錯(cuò)誤寫法,因?yàn)槌A坎荒鼙桓采w。接口常量的概念和類常量是一樣的。class b implements a{const b = 'Class constant';}

問(wèn)答分析

  1. 抽象類和接口分別能直接實(shí)例化嗎?

    • 都不能直接實(shí)例化

  2. 抽象類的方法可以存在方法體嗎?

    • 抽象類中,定義為抽象方法的不可以存在方法體,抽象類中普通方法可以存在方法體。

  3. 抽象方法和普通方法的區(qū)別是什么?

    • 抽象方法只是聲明了其調(diào)用方式(參數(shù)),不能定義其具體的功能實(shí)現(xiàn),普通方法可以定義具體的實(shí)現(xiàn)。

  4. 抽象方法可以是靜態(tài)方法嗎?

    • 可以(PHP5+版本會(huì)出現(xiàn)嚴(yán)格模式提示,PHP7+無(wú)錯(cuò),均可以運(yùn)行)

  5. 抽象類可以存在成員屬性嗎?所有等級(jí)都可以嗎?

    • 可以存在成員屬性,所有等級(jí)都可以,但是子類能直接調(diào)用的只有公開(kāi)屬性

  6. 接口的方法可以存在方法體嗎?

    • 接口方法不可以有方法體

  7. 接口可以存在成員屬性嗎?所有等級(jí)都可以嗎?

    • 不可以存在,接口不包括成員屬性

  8. 普通類可以同時(shí)繼承多個(gè)抽象類嗎?如果可以如何實(shí)現(xiàn)?

    • 抽象類不可以多繼承 (多繼承實(shí)現(xiàn)可以使用Trait)

  9. 普通類可以同時(shí)實(shí)現(xiàn)多個(gè)接口類嗎?如果可以如何實(shí)現(xiàn)?

    • 可以,類可以實(shí)現(xiàn)多個(gè)接口,用逗號(hào)來(lái)分隔多個(gè)接口的名稱。

  10. 抽象類可以實(shí)現(xiàn)接口嗎?如果可以,那抽象類需要實(shí)現(xiàn)接口定義的方法體嗎?

    • 抽象類可以實(shí)現(xiàn)接口,并且不需要實(shí)現(xiàn)接口的方法,但是普通類繼承抽象類后需要全部實(shí)現(xiàn)

  11. 普通類可以既繼承抽象類又實(shí)現(xiàn)接口嗎?

    • 可以

看完上述內(nèi)容,你們掌握抽象類與接口的區(qū)別是什么的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI