成人怡红院-成人怡红院视频在线观看-成人影视大全-成人影院203nnxyz-美女毛片在线看-美女免费黄

站長資訊網
最全最豐富的資訊網站

什么是接口?如何在PHP中使用接口編寫優雅的代碼?

什么是接口?如何在PHP中使用接口?本篇文章帶大家聊聊使用接口編寫更優雅的 PHP 代碼,希望對大家有所幫助!

什么是接口?如何在PHP中使用接口編寫優雅的代碼?

在編程中,確保代碼可讀、可維護、可擴展和易于測試是很重要的;而使用接口,恰恰是我們改進代碼中所有這些因素的方法之一。

目標讀者

本文的目標讀者是對 OOP(面向對象編程)概念有基本了解并在 PHP 中使用繼承的開發人員。如果你知道如何在 PHP 代碼中使用繼承,那么你應該可以很好地理解本文。

什么是接口?

簡而言之,接口只是對類應該做什么的描述,它們可用于確保實現該接口的任何類都將包括在其內部定義的每個公共方法。

接口可以

  • 用于定義類的公共方法;
  • 用于定義類的常量。

接口不可以

  • 被實例化;
  • 用于定義類的私有或受保護方法;
  • 用于定義類的屬性。

接口是用來定義一個類應該包括的公共方法的。記住,你只需要在接口里定義方法的簽名,而不需要包含方法的主體(就像通常在類中看到的方法一樣)。**這是因為接口僅用于定義對象之間的通信,而不是像在類中那樣定義通信和行為。**為了說明這個問題,下面展示了一個定義了幾個公共方法的示例接口:

interface DownloadableReport {     public function getName(): string;      public function getHeaders(): array;      public function getData(): array; }

根據 php.net 文檔我們可以知道,接口有兩個主要用途:

  • 允許開發者創建不同類別的對象,這些對象可以互換使用,因為它們實現了相同的一個或多個接口。常見的例子包含:多個數據庫訪問服務、多個支付網關、不同的緩存策略等。不同的實現之間可以互換,而不需要對使用它們的代碼進行任何修改。

  • 允許函數或方法接受符合接口的參數并對其進行操作,而不關心該對象還可以做什么或它是如何實現的。這些接口通常被命名為 IterableCacheableRenderable 等,來說明這些接口的實際含義。

在 PHP 中使用接口

接口是 OOP(面向對象編程)代碼庫的重要部分。接口能讓我們降低代碼耦合并提高可擴展性。舉個例子,讓我們看看下面這個類:

class BlogReport {     public function getName(): string     {         return 'Blog report';     } }

如你所見,我們定義了一個類,類中有一個函數,返回一個字符串。這樣一來,我們定義了該方法的行為,所以我們知道 getName() 是如何返回字符串的。不過,假設我們在另一個類調用這個方法;這個類不需要關心這個字符串如何構建的,它只關心該方法是否返回內容。舉例來說,讓我們看看如何在另一個類調用此方法:

class ReportDownloadService {     public function downloadPDF(BlogReport $report)     {         $name = $report->getName();          // 下載文件……     } }

盡管上面的代碼正常運行,但我們設想一下,現在想給 UsersReport 類中增加下載用戶報告的功能。顯然,我們不能使用 ReportDownloadService 中的現有方法,因為我們已經強制規定方法只能傳遞 BlogReport 類。因此,我們必須修改把原有的下載方法名稱改掉(避免重名),然后另外再添加一個類似的方法,如下所示:

class ReportDownloadService {     public function downloadBlogReportPDF(BlogReport $report)     {         $name = $report->getName();          // 下載文件……     }      public function downloadUsersReportPDF(UsersReport $report)     {         $name = $report->getName();          // 下載文件……     } }

假設上面的方法中的下載文件部分(注釋掉的部分)使用了相同的代碼,而且我們可以將這些相同的代碼單獨寫成一個方法,但我們仍會有一些重復的代碼(譯者注:指的是每個方法中都會有 $name = $report->getName();)以及有多個幾乎相同的類的入口。這可能會給將來擴展代碼或測試帶來額外的工作量。

例如,假設我們創建了一個新的 AnalyticsReport;我們現在需要向該類添加一個新的 downloadAnalyticsReportPDF() 方法。你可以清晰的看到這個文件將如何膨脹(譯者注:指每增加一個類型,就要增加一個下載方法)。這就是一個使用接口的完美場景!

讓我們從創建第一個接口開始:讓我們將其命名為 DownloadableReport,定義如下:

interface DownloadableReport {     public function getName(): string;      public function getHeaders(): array;      public function getData(): array; }

我們現在可以更新 BlogReportUsersReport 來實現 DownloadableReport 接口,如下例所示。但是請注意,作為演示用途,我故意把 UsersReport 中的代碼寫錯了:

class BlogReport implements DownloadableReport {     public function getName(): string     {         return 'Blog report';     }      public function getHeaders(): array     {         return ['The headers go here'];     }      public function getData(): array     {         return ['The data for the report is here.'];     } }
class UsersReport implements DownloadableReport {     public function getName()     {         return ['Users Report'];     }      public function getData(): string     {         return 'The data for the report is here.';     } }

但當我們嘗試運行代碼的時候,我們將會收到錯誤,原因如下:

  • 缺少 getHeaders() 方法.

  • getName() 方法不包括接口的方法簽名中定義的返回類型。

  • getData() 方法定義了一個返回類型,但它與接口的方法簽名中定義的類型不同。

因此,為了修復 UsersReport 使其正確實現 DownloadableReport 接口,我們可以將其修改為:

class UsersReport implements DownloadableReport {     public function getName(): string     {         return 'Users Report';     }      public function getHeaders(): array     {        return [];     }      public function getData(): array     {         return ['The data for the report is here.'];     } }

現在兩個報告類都實現了相同的接口,我們可以這樣更新我們的 ReportDownloadService

class ReportDownloadService {     public function downloadReportPDF(DownloadableReport $report)     {         $name = $report->getName();          // 下載文件……     }  }

我們現在可以把 UsersReportBlogReport 對象傳入 downloadReportPDF 方法中,而且不會出現任何錯誤。這是因為我們知道該對象實現了報告類的必要方法,并且將返回我們期望的數據類型。

通過向方法傳遞了一個接口,而不是一個具體的類,我們可以根據方法的實際作用(而不是方法的實現原理)來解耦 ReportDownloadService類和這些報告類。

如果我們想創建一個新的 AnalyticsReport,我們可以讓它實現相同的接口。這樣一來,我們不必添加任何新的方法,只需要將報告對象傳遞給同一個的 downloadReportPDF() 方法。如果你正在構建你自己的包或框架,接口可能對你特別有用。你只需要告訴使用者要實現哪個接口,然后他們就可以創建自己的類。例如,在 Laravel 中,我們可以通過實現 IlluminateContractsCacheStore 接口來創建自己的自定義緩存驅動類。

除了能改進代碼之外,我喜歡使用接口的另一個原因是 —— 它們起到了“代碼即文檔”的作用。例如,如果我想弄清楚一個類能做什么,不能做什么,我傾向于先看接口,然后再看實現它的類。接口能夠告訴我們所有可被調用的方法,而不需要我們過多地關心這些方法的底層實現方式是怎樣的。

值得注意的是,Laravel 中的“契約(contract)”和“接口(interface)”這兩個詞語是可互換的。根據 Laravel 文檔,“契約是一組由框架提供的核心服務的接口”。所以,記住:契約是一個接口,但接口不一定是契約。通常情況下,契約只是框架提供的一個接口。關于使用契約的

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
婷婷色香合缴缴情AV第三区| 无码人妻AⅤ一区二区三区水密桃| 色翁荡息又大又硬又粗又爽| 色屁屁WWW影院免费观看入口| 深田えいみ禁欲后被隔壁人妻| 无码AV中文一区二区三区桃花岛| 亚洲AV色香蕉一区二区蜜桃小说| 亚洲日本VA午夜中文字幕一区| 永久免费观看国产裸体美女 | 麻花传媒网站永久入口视频| 全免费A敌肛交毛片免费| 少妇特黄A一区二区三区| 亚洲AV无码成人精品区伊人小说 | 与子乱刺激对白在线播放| 99RE6热这里只精品首页| 八旬老太太BGMBGMBGM性| 国产成人无码AⅤ片在线观看视频 国产成人无码AⅤ片在线观看你 | 国产妇女馒头高清泬20P多| 精品国产日韩一区二区三区| 免费直播视频在线观看| 日韩欧美人妻系列中文字幕一区二区三区 | 久久久亚洲欧洲日产国码AⅤ| 欧美精品VIDEOSSEX少妇| 铜铜铜铜铜铜铜铜好大好硬| 亚洲精品成人AV观看| 91人妻人人澡人人爽人人| 高雅人妻被迫沦为玩物电影BD| 激情久久AV一区AV二区AV三| 女角色翻白眼流口水流眼泪图片| 天堂中文资源在线最新版下载| 亚洲人成网站18禁止一区| Z〇ZOZ〇女人另类ZOZ〇| 国产三级久久久精品麻豆三级| 久久一区二区三区精华液| 日韩精品无码一区二区三区AV| 亚洲AV永久无码精品无码网站| 综合在线视频精品专区| 国产激情无码一区二区三区| 久久亚洲精品无码AV大香| 日韩AV无码成人精品国产| 亚洲成av人片在线观看| H无码精品动漫在线观看导航| 国产午夜激无码AV毛片| 欧美成人免费影片区二区| 无码网站天天爽免费看视频| 中文字幕久久久久人妻| 国产成人AV综合久久| 久久躁夜夜躁天天躁| 四季亚洲AV无码一区在线观看| 影音先锋女人AV女色资源| 高潮毛片无遮挡高清免费| 久久久久成人片免费观看| 肉欲麻豆天美传媒| 一本色道久久HEZYO无码| 国产成人久久精品激情| 蜜桃传媒在线观看免费版7| 无码人妻丰满熟妇一区二区三区 | 亚洲人成人无码一区二区三区| 成人午夜亚洲精品无码区| 久久久久久精品久久久| 天堂√最新版在线| 3D动漫精品啪啪一区二区免费| 国产偷国产偷亚洲清高孕妇| 欧洲无码精品A码无人区| 亚洲精品无码久久| 跟40岁的少妇做一次就不硬了| 免费A级毛片18禁| 亚洲AV无码无在线观看红杏| 成年女人毛片免费观看97| 久久久噜噜噜久噜久久| 五月丁香合缴情在线看| 被公疯狂玩弄的漂亮人妻| 久久综合九色综合久99| 无码任你躁久久久久久| 拔萝卜全程不该盖被子怎么办| 久久久噜噜噜久久久精品| 午夜丰满少妇性开放视频 | 97一期涩涩97片久久久久久久| 娇妻被别人玩弄至高潮| 天天澡天天揉揉AV无码| JEALOUSVUE成熟| 久久丫免费无码一区二区| 亚洲AV成人无码一区二区三区在 | 99国精品午夜福利视频不卡99| 精品国产日韩一区二区三区| 我和公GONG在厨房日本电影| WWW夜插内射视频网站| 开丫头小嫩苞疼死了| 亚洲成av人无码| 国产粗语刺激对白ⅩXX| 日本高清在线一区二区三区| 中文字幕无码专区人妻系列| 久久96热在精品国产高清| 亚洲6080YY久久无码产自国| 高潮到不停喷水的免费视频| 欧洲精品码一区二区三区| 综合 欧美 小说 另类 图| 久久精品中文字幕| 亚洲第一无码AV无码专区| 国产精品无码AV天天爽播放器| 日本熟妇色XXXXXBBB日本| AV无码免费无禁网站| 久久亚洲精品无码VA大香大香| 亚洲精品二区国产综合野狼| 国产日产欧产美韩系列| 玩弄肥美高大的熟妇| 夫妇交换聚会群4P疯狂大战| 日产精品1卡二卡三卡| CHINESETUBE国产在线| 男人边吃奶边揉好爽免费视频 | 精JAVAPARSER乱偷| 亚洲AV成人无码久久WWW | 成人免费视频一区二区| 人妻丰满熟妇av无码区HD| BBWBBW肥妇BBWBBW| 女人与公豬交交30分钟视频| 中文字幕JUL975老公不在| 久久这里精品国产99丫E6| 一区二区三区精品视频免费播放| 久久99精品久久久久久蜜芽| 亚洲精品乱码久久久久久| 狠狠色狠狠色综合| 亚洲爆乳成AV人在线视菜奈实| 国内永久免费CRM系统Z在线| 亚洲AV日韩AV无码AV一区二| 国外精品视频在线观看免费| 亚洲METART人体欣赏| 机密重案之致命诱惑| 亚洲高清中文字幕在线看不卡| 好男人资源在线观看好| 亚洲成在人线AV| 精产国品一二三产区区別| 亚洲乱码av一区二区三区| 精品无码无人网站免费视频| 亚洲熟妇成人精品二区蜜臀| 精品一区二区AV天堂| 伊人久久大香线蕉AV不变影院| 老司机精品成免费视频| 18禁强伦姧人妻又大又| 欧美激情一区蜜桃传媒| 宝宝湿透了还嘴硬怎么回事 | 丰满肥女巨肥BWWBBWW| 特级AAAAAAAAA毛片免费视频| 国产精品秘 入口A级熟女| 亚洲A∨无码无在线观看| 精品国产乱码久久久久久1区2区 | 少妇粗大进出白浆嘿嘿视频| 国产成人无码精品XXXX| 小婷又软又嫩又紧水又多的视频| 国内老熟妇乱子伦视频| 亚洲一区二区三区中文字幕在线| 久久夜色精品国产噜噜亚洲AV| 97久久天天综合色天天综合色H| 日本VS亚洲VS韩国一区三区| 国产成人乱色伦区小说| 亚洲AV永久无码精品成人| 久久精品国产亚洲AV久| 14萝自慰专用网站| 日本适合十八岁以上的护肤品一 | 午夜不卡AV免费| 精品亚洲国产AⅤ在线| 中文字幕在线不卡精品视频99| 人妻少妇粗大持久满足| 国产成人亚洲精品青草天美| 亚洲国产成人无码AV在线影院 | 无码精品人妻一区二区三区影院| 狠狠综合久久久久综合网站| 真人作爱试看90分钟免费影视| 人妻AV无码一区二区三区| 成人艳情一二三区| 亚洲AV日韩AV永久无码色欲| 麻豆丰满少妇CHINESE| 超碰CAO已满18进入| 亚洲一线产区二线产区区别在哪儿 | 777精品久无码人妻蜜桃 | 纯肉无遮挡H肉动漫在线观看国产 纯肉无遮挡H肉动漫在线观看3D | 中文字幕日韩欧美一区二区三区| 日本少妇ASS浓精PICS| 国产无遮挡免费真人视频在线观看 | 久久亚洲色WWW成人网址| 别揉我奶头~嗯~啊~视频| 亚洲AVSSS在线观看| 免费人成视频网站在线18| 粉嫩小泬无遮挡久久久久久小说| 亚洲精品卡一卡三卡四卡乱码| 农民工猛吸女大学奶头| 国产精品久久福利新婚之夜| 亚洲乱色伦图片区小说| 特级毛片A级毛片免费观看网站| 狠狠亚洲婷婷综合色香五月加勒比 | 中国 韩国 日本 免费看片| 久久久久久亚洲精品成人| 成人毛片100部免费看| 亚洲成A∨人片在线观看不卡| 欧美成人精品视频在线不卡| 国产精品免费久久久久影院| 中文字幕丰满乱子伦无码专区 | 精品国产成人国产在线观看| e无遮挡粉嫩小泬久久久久久久| 亚洲AⅤ天堂AV天堂无码麻豆|