0

0

什么是接口?如何在PHP中使用接口编写优雅的代码?

青灯夜游

青灯夜游

发布时间:2022-07-25 20:17:18

|

3643人浏览过

|

来源于掘金社区

转载

什么是接口?如何在php中使用接口?本篇文章带大家聊聊使用接口编写更优雅的 php 代码,希望对大家有所帮助!

什么是接口?如何在PHP中使用接口编写优雅的代码?

在编程中,确保代码可读、可维护、可扩展和易于测试是很重要的;而使用接口,恰恰是我们改进代码中所有这些因素的方法之一。

目标读者

本文的目标读者是对 OOP(面向对象编程)概念有基本了解并在 PHP 中使用继承的开发人员。如果你知道如何在 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() 方法。你可以清晰的看到这个文件将如何膨胀(译者注:指每增加一个类型,就要增加一个下载方法)。这就是一个使用接口的完美场景!

Whimsical
Whimsical

Whimsical推出的AI思维导图工具

下载

让我们从创建第一个接口开始:让我们将其命名为 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 中,我们可以通过实现 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速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

php

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Java 桌面应用开发(JavaFX 实战)
Java 桌面应用开发(JavaFX 实战)

本专题系统讲解 Java 在桌面应用开发领域的实战应用,重点围绕 JavaFX 框架,涵盖界面布局、控件使用、事件处理、FXML、样式美化(CSS)、多线程与UI响应优化,以及桌面应用的打包与发布。通过完整示例项目,帮助学习者掌握 使用 Java 构建现代化、跨平台桌面应用程序的核心能力。

37

2026.01.14

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 高性能
PHP 高性能

本专题整合了PHP高性能相关教程大全,阅读专题下面的文章了解更多详细内容。

37

2026.01.13

MySQL数据库报错常见问题及解决方法大全
MySQL数据库报错常见问题及解决方法大全

本专题整合了MySQL数据库报错常见问题及解决方法,阅读专题下面的文章了解更多详细内容。

19

2026.01.13

PHP 文件上传
PHP 文件上传

本专题整合了PHP实现文件上传相关教程,阅读专题下面的文章了解更多详细内容。

16

2026.01.13

PHP缓存策略教程大全
PHP缓存策略教程大全

本专题整合了PHP缓存相关教程,阅读专题下面的文章了解更多详细内容。

6

2026.01.13

jQuery 正则表达式相关教程
jQuery 正则表达式相关教程

本专题整合了jQuery正则表达式相关教程大全,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

交互式图表和动态图表教程汇总
交互式图表和动态图表教程汇总

本专题整合了交互式图表和动态图表的相关内容,阅读专题下面的文章了解更多详细内容。

45

2026.01.13

nginx配置文件详细教程
nginx配置文件详细教程

本专题整合了nginx配置文件相关教程详细汇总,阅读专题下面的文章了解更多详细内容。

9

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 8.6万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 7万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号