ホームページ  >  記事  >  バックエンド開発  >  インターフェースとは何ですか? PHP のインターフェイスを使用してエレガントなコードを記述するにはどうすればよいですか?

インターフェースとは何ですか? PHP のインターフェイスを使用してエレガントなコードを記述するにはどうすればよいですか?

青灯夜游
青灯夜游転載
2022-07-25 20:17:183214ブラウズ

インターフェースとは何ですか? PHP でインターフェイスを使用するにはどうすればよいですか?この記事では、インターフェイスを使用してよりエレガントな PHP コードを記述する方法について説明します。

インターフェースとは何ですか? PHP のインターフェイスを使用してエレガントなコードを記述するにはどうすればよいですか?

プログラミングでは、コードが読みやすく、保守しやすく、拡張可能で、テストが容易であることを保証することが重要です。インターフェイスを使用することで、まさにこれらすべての要素を改善することができます。コード メソッドの 1 つ。

対象読者

この記事は、OOP (オブジェクト指向プログラミング) の概念を基本的に理解し、PHP で継承を使用する開発者を対象としています。 PHP コードで継承を使用する方法を知っている場合は、この記事をよく理解できるはずです。

インターフェースとは何ですか?

要するに、インターフェイスはクラスが何をすべきかを単に記述したものであり、インターフェイスを実装するクラスに、インターフェイス内で定義されているすべてのパブリック メソッドが確実に含まれるようにするために使用できます。

Interfacecan:

  • はクラスのパブリック メソッドの定義に使用され、
  • はクラスの定数の定義に使用されます。

インターフェイスはインスタンス化できません。

    はインスタンス化されます。
  • は、クラスのプライベート メソッドまたは保護されたメソッドを定義するために使用されます。
  • クラスの属性を定義するために使用されます。
Interface は、クラスに含める必要があるパブリック メソッドを定義するために使用されます。インターフェース内でメソッドのシグネチャを定義するだけでよく、(通常のクラス内のメソッドのように) メソッドの本体を含める必要はないことに注意してください。 **これは、インターフェイスはオブジェクト間の通信を定義するためにのみ使用され、クラスのような通信や動作を定義するためには使用されないためです。 **この問題を説明するために、いくつかのパブリック メソッドを定義するインターフェイスの例を以下に示します。

interface DownloadableReport
{
    public function getName(): string;

    public function getHeaders(): array;

    public function getData(): array;
}

php.net ドキュメントによると、インターフェイスには 2 つの主な目的があることがわかります。 :

  • 開発者は、同じインターフェイスを実装しているため、互換的に使用できるオブジェクトの異なるクラスを作成できます。一般的な例には、複数のデータベース アクセス サービス、複数の支払いゲートウェイ、さまざまなキャッシュ戦略などが含まれます。異なる実装は、それらを使用するコードを変更することなく交換できます。

  • 関数またはメソッドは、オブジェクトが他にできることやその実装方法を気にせずに、インターフェイスに準拠するパラメーターを受け取り、それらのパラメーターを操作できるようにします。通常、これらのインターフェイスには、これらのインターフェイスの実際の意味を示すために、

    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();

        // 下载文件……
    }
}
上記のメソッドのダウンロード ファイル部分 ( out 部分) は同じコードを使用しており、これらの同じコードを別のメソッドに記述することもできますが、それでもコードの一部が繰り返されることになります (翻訳者注: 各メソッドの

を指します $name = $report->getName ();) ほぼ同じクラスのエントリが複数あります。これにより、将来的にコードの拡張やテストのための追加作業が発生する可能性があります。

たとえば、新しい

AnalyticsReport を作成するとします。このクラスに新しい downloadAnalyticsReportPDF() メソッドを追加する必要があります。このファイルがどのように拡張されるかがはっきりとわかります。これはインターフェイスを使用するのに最適なシナリオです。

最初のインターフェースを作成することから始めましょう。

DownloadableReport という名前を付け、次のように定義します。

interface DownloadableReport
{
    public function getName(): string;

    public function getHeaders(): array;

    public function getData(): array;
}
これで、

BlogReport と # を更新できるようになります。次の例に示すように、##UsersReport を使用して DownloadableReport インターフェイスを実装します。ただし、デモンストレーションの目的で、UsersReport のコードを意図的に間違って記述したことに注意してください: <pre class="brush:php;toolbar:false">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.'];     } }</pre> <pre class="brush:php;toolbar:false">class UsersReport implements DownloadableReport {     public function getName()     {         return ['Users Report'];     }     public function getData(): string     {         return 'The data for the report is here.';     } }</pre> しかし、コードを実行しようとすると、次の理由でエラーが発生します :

  • 缺少 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 中,我们可以通过实现 Illuminate\Contracts\Cache\Store 接口来创建自己的自定义缓存驱动类。

除了能改进代码之外,我喜欢使用接口的另一个原因是 —— 它们起到了“代码即文档”的作用。例如,如果我想弄清楚一个类能做什么,不能做什么,我倾向于先看接口,然后再看实现它的类。接口能够告诉我们所有可被调用的方法,而不需要我们过多地关心这些方法的底层实现方式是怎样的。

值得注意的是,Laravel 中的“契约(contract)”和“接口(interface)”这两个词语是可互换的。根据 Laravel 文档,“契约是一组由框架提供的核心服务的接口”。所以,记住:契约是一个接口,但接口不一定是契约。通常情况下,契约只是框架提供的一个接口。关于使用契约的更多信息,我建议大家可以阅读这一篇文档。它很好地剖析了契约究竟是什么,也对使用契约的方式与场景做了一定的叙述。

小结

希望通过阅读这篇文章,你能对什么是接口、如何在 PHP 中使用接口以及使用接口的好处有一个简单的了解。

原文地址:https://dev.to/ashallendesign/using-interfaces-to-write-better-php-code-391f

原文作者:Ash Allen

译者:kamly、jaredliw

推荐学习:《PHP视频教程

以上がインターフェースとは何ですか? PHP のインターフェイスを使用してエレガントなコードを記述するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。