久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      一文講解接口含義及如何用接口寫高質(zhì)量PHP代碼

      概述

      在編碼中,有一個重要的事情是確保你的代碼是可讀的、可維護的、可擴展的、易于測試的。我們可以改善這些問題的方法之一就是使用接口(interface)。

      目標(biāo)受眾

      本文針對對 OOP(object oriented programming)概念和 PHP 中的繼承有基本理解的開發(fā)者,如果你知道如何在 PHP 中使用繼承,那么這篇文章會更容易理解一些。

      什么是接口?

      基本上,接口描述了一個類「該做什么」。接口被用于確保實現(xiàn)接口的任何類中都包含接口規(guī)定的公共方法。

      接口可以

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

      接口不可以

      • 單獨實例化。
      • 用于定義類中的私有(private)或保護(protected)方法。
      • 用于定義類中的屬性。

      接口口用于定義一個類中應(yīng)該包括的公共方法。需要記住的是,接口只定義了方法名和參數(shù)以及返回值,但不包含方法體。這是因為接口僅用于定義對象間的通信,而不是定義類之間通信的具體行為。為了給出一點上下文,這個實例展示了一個定義了幾個公共方法的示例接口:

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

      根據(jù) php.net 介紹,接口有兩個主要用途:

      1. 允許開發(fā)人員創(chuàng)建不同類的對象,這些對象可以互換使用,因為它們實現(xiàn)相同的接口。一個常見的例子是多個數(shù)據(jù)庫訪問服務(wù),多個支付網(wǎng)關(guān)或不同的緩存策略??梢愿鼡Q不同的實現(xiàn),而無需對使用它們的代碼進行任何更改。
      2. 允許函數(shù)或方法接受符合接口的參數(shù)并對其進行操作,而不關(guān)心對象還可以做什么或它是如何實現(xiàn)的。這些接口通常被命名為 Iterable,Cacheable,Renderable 等等來描述行為的含義?!就扑]學(xué)習(xí):《PHP視頻教程》】

      在 PHP 中使用接口

      接口是 OOP (面向?qū)ο缶幊? 代碼中非常重要的一部分。它們允許我們將代碼解耦并提高可擴展性。舉一個例子,讓我們看看下面這個類:

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

      如您所見,我們已經(jīng)定義了一個帶有返回字符串的方法的類。通過這樣做,我們已經(jīng)確定了方法的行為,因此我們可以看到getName()是如何構(gòu)建返回的字符串的。但是,假設(shè)我們在另一個類中的代碼中調(diào)用此方法。另一個類并不會關(guān)心字符串是如何構(gòu)建的,它只關(guān)心它是否被返回。例如,讓我們看看如何在另一個類中調(diào)用此方法:

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

      盡管上面的代碼已經(jīng)可以用了,讓我們設(shè)想一下,若是我們現(xiàn)在想要在 UserReport 類中增加一個下載用戶報告的方法。當(dāng)然,我們不能使用 ReportDownloadService 中已經(jīng)存在的方法,因為我們已經(jīng)強制只能傳入一個 BlogReport 類。因此,我們必須重命名現(xiàn)有方法,再添加一個新的方法。像這樣:

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

      雖然你實際看不到,但我們假設(shè)上述的類中,其余的方法都使用相同的代碼來構(gòu)建下載。我們可以將公共的代碼提升為方法,但我們?nèi)匀粫幸恍┕驳拇a。除此之外,我們還有多個進入這個類的幾乎是相同代碼的入口。這可能會在未來嘗試擴展代碼或添加測試功能時導(dǎo)致額外的工作量。

      舉個例子,我們創(chuàng)建一個新的 AnalyticsReport;我們現(xiàn)在需要為這個類增加一個新的 downloadAnalyticsReportPDF() 方法。這時你可能會觀察到這個文件正在快速增長。這時就是使用接口的絕佳時機。

      我們從創(chuàng)建一個接口開始。我們要創(chuàng)建一個叫做 DownloadableReport 的接口,并這樣定義:

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

      我們現(xiàn)在要更改 BlogReportUsersReport 來實現(xiàn) DownloadableReport 接口,如下所示。我故意寫錯了 UsersReport 的代碼來演示一些東西。

      class BlogReport implements DownloadableReport {     public function getName(): string     {         return '博客報告';     }      public function getHeaders(): array     {         return ['頭在這'];     }      public function getData(): array     {         return ['報告的數(shù)據(jù)在這里'];     } }
      class UsersReport implements DownloadableReport {     public function getName()     {         return ['用戶報告'];     }      public function getData(): string     {         return '報告的數(shù)據(jù)在這里';     } }

      如果我們嘗試運行這段代碼,我們會得到報錯,原因是:

      1. 找不到 getHeaders() 方法。
      2. getName() 方法返回類型在接口中定義的方法返回值類型中。
      3. getData() 方法定義了返回類型,但和接口中定義的返回類型不同。

      因此,要讓 UsersReport 正確地實現(xiàn) DownloadableReport 接口,我們需要作如下變動:

      class UsersReport implements DownloadableReport {     public function getName(): string     {         return '用戶報告';     }      public function getHeaders(): array     {        return [];     }      public function getData(): array     {         return ['報告的數(shù)據(jù)在這里'];     } }

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

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

      現(xiàn)在我們向 downloadReportPDF() 方法傳入了 UsersReportBlogReport 對象,沒有任何錯誤出現(xiàn)。這是因為我們現(xiàn)在知道了報告類所需要的必要方法,并且報告類會按照我們預(yù)期的類型返回數(shù)據(jù)。

      向方法傳入接口,而不是向類傳入接口,這樣的結(jié)果使得 ReportDownloadService 和報告類產(chǎn)生松散耦合,這根據(jù)的是方法做什么,而不是如何做。

      如果我們想要創(chuàng)建一個新的 AnalyticsReport,我們需要讓它實現(xiàn)相同的接口,然后它就會允許我們將報告類實例傳入相同的 downloadReportPDF() 方法中,而不用添加其他新的方法。如果你正在構(gòu)建自己的應(yīng)用或框架,想要讓其他開發(fā)人員有創(chuàng)建給他們自己的類的功能,這將非常有用。舉個例子,在 Laravel 中,你可以通過實現(xiàn) IlluminateContractsCacheStore 接口來創(chuàng)建自定義的緩存類。

      除了使用接口來改進代碼外,我更傾向于喜歡接口的「代碼即文檔」特性。舉個例子,如果我想要知道一個類能做什么和不能做什么,我更喜歡在查看類之前先查看接口。它會告訴我所有可調(diào)用的方法,而不需要關(guān)心這些方法具體是怎么運行的。

      對于像我這樣的 Laravel 開發(fā)者來說,值得注意的一件事是,你會經(jīng)??吹?接口 interface契約 contract 交替使用。根據(jù) Laravel 文檔,「Laravel 的契約是一組定義了框架提供的核心服務(wù)的接口」。因此,契約是一個接口,但接口不一定是契約。通常來說,契約只是框架提供的一個接口。有關(guān)契約的

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號