PHP - 如果抽象类中的所有方法都是抽象的,那么接口和抽象类有什么区别

2023-12-20

抽象类可能有也可能没有抽象方法,但接口仅具有未实现的方法。那么,如果我的抽象类将其所有方法都标记为抽象,那么使用接口有什么区别和优点呢?


接口和抽象
使用的真正威力可以在具有大量类的庞大 API 中体现出来,这些类遵循经过深思熟虑的灵活结构以供未来编码。无论它是否会发生——你永远不知道代码是否会被扩展。接口仅出于语义原因而使用。想象一下,您扩展了一个已弃用的 API 版本,并负责编辑/更改/实现/更新/改进/扩展/修改代码以使其保持最新,无论原因是什么。如果你不向前思考,你最终会感到沮丧。

小型 API 可以在没有接口的情况下创建,而这正是大多数人认为接口是不必要的地方。但一旦它们变大,它们就会失去灵活性。他们为您提供一份课程合同,提醒您需要什么并保持概览。接口必须有公共方法,如果有受保护或私有方法,只需在实现了接口的类的公共方法中返回它们即可。

就像您已经解释的那样,接口需要实现特定的方法,抽象类不需要它,因为您很可能无论如何都会扩展它们。方法可以重新定义,并且抽象方法必须在子类中定义。接口中提到的方法只是告诉您与接口有契约的类必须定义这些方法。它可以是多个接口,您不会像使用抽象类那样继承它们。

像这样思考
其中的逻辑是预测您计划构建的未来。无论是建筑、基础设施还是工厂的大规模生产。就像您对文件夹中的书签、书籍、图像等项目进行排序一样。因为您知道,如果不对其进行排序,则需要更长的时间才能找到特定图像。抽象和接口的语义目的是相似的,尤其是在庞大的 API 中。

  • 接口代表可能性和需求的框架。
  • 抽象保留了与派生上下文相关的概念信息。

我将向您展示一个具有简化内容的 API 开始的典型结构,其中接口和抽象类对于未来的扩展具有真正的用途。

/* Considering, this project will be widely expanded up to huge complexity. 
   This is a flexible base structure, for developers working in team. Imagine 
   there could be lots more variation of styles for certain purposes. */


// OOP STRUCT
// You might want to define multiple interfaces to separate the project
interface iString {
    // These methods MUST be defined or else the developer receives an error
    public function getContent();
    public function description($desc);
}

/* Devs might want to add an additional method later on. 
   Traits are useful for quick use. (optional) */

trait desc {

    private $desc;

    public function description($desc) {
        return $this->desc;
    }
}


/* This is the base class for the content which requires a declaration 
   of methods being described in the interface */

class contents implements iString {

    use desc; // use the method defined in a trait
    private $str;

    public function __construct($str) {
        $this->str = $str;
    }

    public function getContent() {
        return $this->str;
    }
}


/* Or devs often consider abstract classes as the real base of the whole project/app.
   Abstract classes allow the use of methods that can be modified/declared for further use in derived classes.
   Interfaces can't do that */

abstract class stylize {

    private $str;

    // This typehint below makes sure that this value is assigned on interface
    public function __construct(iString $str) { 
        $this->str = $str;
    }

    public function style() {
        return $this->str->getContent();
    }

    abstract public function getContent();
}


// EXTENDED CLASSES 
class bold extends stylize {
    // Extended classes have to define abstract methods inherited from an abstract class. Non-abstract methods are not needed.
    public function getContent() {
        return "<strong>".parent::style()."</strong>";
    }
}

class underline extends stylize {

    public function getContent() {
        return "<u>".parent::style()."</u>";
    }
}

class upperCase extends stylize {

    public function getContent() {
        return strtoupper(parent::style());
    }
}


// PROCEDUAL OUTPUT

// A tiny shortcut
$e = function($desc,$str) { echo $desc.": ".$str->getContent()."<br>"; };

// Content being used
$content = new contents('Hello World.');
$e("Normal",$content);

// Content being styled
$bold = new bold($content);
$underline = new underline($content);
$upper = new upperCase($content);

// Renders content with styles        
$e("Bold",$bold);
$e("Underline",$underline);
$e("Uppercase",$upper);

结论
以应用文本内容的样式为例可能不够吸引人。但除此之外,它仍然是一样的——如果它做了它应该做的事情,那么它就完成了。就像我要构建一个可扩展的电子邮件配置 API 作为 CMS 的模块一样。该结构在正确的编码中具有语义过程。

Tipps
我建议您继续使用这种模式在小型项目中学习,即使您认为界面不值得。继续这样做,直到把它放进去。我个人给你的建议: 如果您认为您不知道从哪里开始以及在哪个项目上尝试,那么请按照以下逻辑尝试现实世界的示例:



Vehicles (abstract class)
-> Ferrari (extended class)
-> Truck (extended class)

both have wheels (property)
both must be able to drive (method)

they perform a 1mile match race on a street (abstract method)

one is a slowpoke (extended property)
one is red one is blue (extended property)

and later a 3rd one comes and its a train (extended class)

who's going to win (some method)

Instantiate all vehicles and maintain privileges over interface and 
abstraction.
...something like this...
  

通常,包含巨大主体的类应该被分隔在单个文件中+包含这些+定义一个命名空间。否则代码墙会让你或其他人感到疲倦。使用Eclipse https://www.eclipse.org/downloads/,维护 OOP 的最佳应用程序。

另外,如果它适合您的项目,请使用phUML如果你有。如果您有很多相关的类,它会为您当前的构建生成一个图形图表。

phUML 是 PHP 中基于 UML 的 API。它是一个开源项目,可以为几乎所有流行的编程语言生成任何视觉方案。我经常使用它,不仅仅是 PHP。只需将其克隆到Github https://github.com/jakobwesthoff/phuml或从下载大商合达网 http://dasunhegoda.com/class-diagram-from-php-code-using-phuml/867/并按照那里的安装指南进行操作。
您可能也会对此感兴趣:接口上的类型提示 http://radify.io/blog/type-hinting-in-php-good-or-bad-practice/

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PHP - 如果抽象类中的所有方法都是抽象的,那么接口和抽象类有什么区别 的相关文章

  • 通过JS Laravel访问存储目录

    有没有办法访问storage目录 该目录已经链接到publicJS 中的目录 我正在尝试制作一个上传图片的表单 验证脚本 if request gt hasFile photos marker gt photos request gt ph
  • 如何在php中使用preg添加html属性

    我正在寻找在 php 中编写一个脚本来扫描 html 文档并根据它找到的内容向元素添加新标记 更具体地说 我是扫描文档并为每个元素搜索CSS标记 float right left 如果找到它 它会添加align right left 基于它
  • 将 MySQL 结果作为 PHP 数组

    mysql 表 config name config value allow autologin 1 allow md5 0 当前的 php 代码 sth mysql query SELECT rows array while r mysq
  • 如何使用 Google 帐户对我们网站中的用户进行身份验证

    如何在我们的网站中使用 Google 帐户对用户进行身份验证 我希望用户重定向到谷歌登录页面 然后将他重定向到我的网站 我想要这个 PHP 实现 你要OAuth http code google com apis accounts docs
  • jquery上传完成后重定向到新页面

    我正在尝试让这个 jquery 工具与我的网站一起使用以进行文件上传 https github com blueimp jQuery File Upload https github com blueimp jQuery File Uplo
  • PHP 基本身份验证 file_get_contents() [重复]

    这个问题在这里已经有答案了 我需要从网站解析一些 XML 数据 XML 数据是原始格式 但在我需要进行身份验证之前 基于基本网络服务器的身份验证 使用用户名和密码 I tried homepage file get contents htt
  • 尝试获取 Google accessToken

    看起来 无论我做什么 谷歌都在竭尽全力阻止我完成这个研究项目 我的项目让我使用 Google 电子表格作为数据库 并使用所述电子表格中的数据执行程序化的 Google 图片搜索 并向最终用户显示一些结果 设置说明 我开始按照此处的说明进行操
  • PHP使用auto_increment生成短唯一ID?

    我想生成一个简短的 唯一的 ID 而不必检查冲突 我目前正在做类似的事情 但是我当前生成的 ID 是随机的 并且在循环中检查冲突很烦人 并且如果记录数量显着增加 将会变得昂贵 通常担心冲突不是问题 但我想要生成的唯一 ID 是一个由 5 8
  • 使用 NSError 检查错误的正确结构

    我正在编写各种例程 并尽力保持其整洁和重构 我正在创建的方法开始看起来与此代码类似 IBAction buttonPress id sender Create Document Shopping List with this documen
  • 如何在 Smarty 中打印 json

    我从 api 获取 json 如何使用 Smarty 打印 json Json格式 first name jinu last name mk loginid email protected cdn cgi l email protectio
  • PHP 错误警告:参数 1 应该是引用

    我 熟悉 PHP 我的朋友的网站因错误而崩溃 Warning Parameter 1 to Some function name expected to be a reference value given in public html i
  • UTF-8、PHP、Win7 - 现在是否有解决方案可以使用 php 在 Win 7 上保存 UTF-8 文件名?

    更新 只是为了不让您阅读所有内容 PHP 开头 7 1 0alpha2 在 Windows 上支持 UTF 8 文件名 感谢阿纳托尔 贝尔斯基 根据 stackoverflow 上的一些链接 我找到了部分答案 https stackover
  • magento成功页面变量

    我正在尝试捕获一些 magento 成功页面变量以传递给我们的广告公司 到目前为止 我已经得到了这个 但变量没有输出任何内容 数据需要采用以下格式 price1 price2 price3 qty1 qty2 qty3 sku1 sku2
  • 简单的dom php解析获取自定义数据属性值

    HTML div class something ddsf PHP foreach dom gt find something data rel as this var dump this gt attr 我尝试了这个但错误 在其文档中找不
  • 使用 PHP 和 OAuth 访问 SkyDrive

    我想使用 PHP 访问 skyDrive 我想检索文件和文件夹列表 下载 上传和删除文件 我有一个 microsoft dev clientID 和 clientSecret 有人可以帮助我开始使用 OAuth 连接到 skyDrive 并
  • 监听文件夹和文件(更改)

    可以直接在 PHP 或 Node 上监听文件夹和文件的更改 通过事件 还是我需要创建自己的方法来执行此操作 Example 我需要听文件夹 user 如果我将一些文件添加到该目录中 PHP 或 Node 会收到信息并运行PathEvent
  • 接口中的构造方法

    接口中的构造方法不好吗 为什么人们认为有人想要实例化接口 我们想要做的是强制实现者实现构造函数 就像其他接口方法一样 接口就像一个合同 假设我有一个接口 Queue 并且我想确保实现者创建一个带有一个参数的构造函数 该构造函数创建一个单例队
  • 谷歌日历手表过期时间超过1个月怎么办?

    我将我的 CRM 系统与 Google 日历同步 为此 我要求push notifications从我的用户 Google 日历到我的系统 我已经成功创建了手表 并将过期时间设置为2030年 但是当我收到手表事件的响应时 它显示手表的过期时
  • 防止Java实例化的正确方法[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用“INSERT ... ON DUPLICATE KEY UPDATE”插入多条记录

    我的表结构 table marks 我的目标 我想用条件插入或更新多条记录 我目前正在通过此查询进行检查 第一步 SELECT FROM marks WHERE student 115 AND param 1 第二步 if records

随机推荐

  • 无法 npm 安装 canvas [Windows 上的 NodeJs]?

    我正在尝试使用 ag psd 包来操作 psd 文件 它仅适用于结构 但如果您也想读取图像数据 则会遇到错误 错误如下 Cannot find module canvas code MODULE NOT FOUND 但如果我尝试安装画布 我
  • 每个派生表必须有自己的别名 - 来自组合降序 MySQL 的错误

    我想通过来自两个不同列的两个 strtotime 时间戳对一个 mysql 表进行排序 我有以下 mysql 命令 SELECT FROM SELECT 1 AS table vid req timestamp AS timestamp t
  • 失败 [INSTALL_FAILED_INVALID_APK]

    当我单击运行刚刚在 Android Studio 0 2 10 中创建的项目并选择我的 Android 通过 USB 连接并通过 USB 进行调试 时 出现以下错误 Waiting for device Target device 0123
  • Twilio 未通过 AWS Lambda 实时发送 WhatsApp 消息

    很抱歉这篇文章很长 但这只是为了更好地解释 因为英语不是我的母语 我正在使用 API Gateway Lambda 通过 POST 请求发送 WhatsApp 消息 我遇到过这种奇怪的行为 看起来 Twilio 需要在 2 个请求或一段时间
  • 如何为 flutter 中的资产创建 APK 扩展文件

    我创建了一个 flutter 应用程序 其中包含大小约为 450mb 的视频资源 我已经在Apple应用商店中成功发布了该应用程序 但 Google Play 不接受我的 APK 因为它超过了 200mb 的限制 我尝试采用创建 APK 扩
  • 在 Visual Studio 2015 中使用 Protractor 测试 ASP.NET Core 应用程序

    我有一个基于核心模板包中的 angular2 模板的 ASP NET Core 项目 我添加了第二个使用 xunit 和量角器进行项目 http dotnetthoughts net end to end testing angularjs
  • 为什么自定义并发队列上的dispatch_sync会死锁

    在自定义并发dispatch queue上使用dispatch sync时 我发现我的应用程序出现间歇性死锁 我正在使用类似于中描述的方法迈克 阿什的博客 http www mikeash com pyblog friday qa 2011
  • Curl 7.43.0 不会在 MSVC 2013 中构建

    在 Visual Studio 2013 中从 cUrl 7 43 0 构建 libcurl w ssl 时 编译器报告以下错误 1 gt 构建开始 项目 libcurl 配置 DLL 调试 DLL OpenSSL DLL LibSSH2
  • 我如何滥用空合并运算符?这是否正确评估“null”?

    我试图在 Unity 的 C 脚本中使用空合并运算符 我的项目脚本运行时设置为 NET 4 x 因此它应该可以正常工作 问题在于 即使 LEFT 操作数的计算结果为 null 它也无法正确返回 RIGHT 操作数 这是一个示例声明不起作用当
  • Terraform:在另一个资源中引用在 for_each 中创建的资源

    当我有一个托管区域时 我可以轻松创建该区域 然后通过按名称引用托管区域 在委托账户中为该区域创建 NS 记录 编辑为了避免混淆 这是我想要实现的目标 但对于多个托管区域并且域的所有者是管理帐户 https dev to arswaw cre
  • 网站移动兼容性

    如何制作既兼容桌面浏览器又兼容移动浏览器的网站 针对桌面和移动设备的替代 CSS 文件有一个技巧 在 HTML header 中实现如下
  • Pygame:为什么我无法绘制圆形精灵

    我创建了以下代码 但不知道为什么无法创建圆形精灵 我真的在网上到处找 发现了同样的事情 但当我尝试它时 它不起作用 我想我只需要在更新和其他代码行之间切换 我是 pygame 的新手 所以请非常明确 谢谢 这是主要功能 import pyg
  • 在 MvcSiteMapProvider 中为具有动态参数的 DynamicNode 创建子节点

    我正在使用 MvcSiteMapProvider 2 2 1 http mvcsitemap codeplex com 并且当这些子节点具有动态参数 id 时 在动态节点下创建子节点 使用dynamicNodeProvider 时遇到问题
  • Android 中双击耳机按钮

    我使用此代码来检测广播接收器中耳机按钮的单击和双击 int d 0 Override public void onReceive Context context Intent intent String intentAction inten
  • 插入包含页脚的 UICollectionView 部分时出现问题

    我有一个典型的 UICollectionView 它以垂直方式使用 UICollectionViewFlowLayout 我正在使用带有分页的 REST API 来填充集合视图 为了触发下一页的下载 我在请求页脚布局时使用委托 UIColl
  • codeigniter 中的会话更新

    您好 我想问一下是否可以更新保存在 codeigniter 数据库中的会话数据 我有一个会话 userdata roleID name logged in 这样当有人登录时 我只需调用 data name this gt session g
  • 发送数据包之前读取 TCP 序列号

    我正在 Linux 下编写 C C 客户端 服务器程序 假设客户端要向服务器发送一条消息 m 客户端是否可以在发送 m 之前读取携带 m 的数据包的 TCP 序列号 事实上 我想append将此序列号发送给 m 并发送结果数据包 嗯 事情比
  • 嵌套 If/Else 的更简洁替代方案

    我主要关注 create animal 中 if else 的替代方案 如果有更专业的方法来处理这个问题 在这种情况下 它是一个基于确定动物是什么所需的可变数量特征的分类器 由于人类是唯一会说英语的动物 因此该属性就足够了 但如果熊和狮子只
  • 动画移动 UIButton 在移动时不响应触摸/点击

    我正在尝试为 UIButton 制作动画以在屏幕上移动 用户可以随时触摸它 然而 它似乎在移动时不响应触摸 仅在动画的开始和结束时响应 我想这是因为按钮本身没有移动 只是它的图像在移动 我有什么想法可以解决这个问题吗 到目前为止 这是我的代
  • PHP - 如果抽象类中的所有方法都是抽象的,那么接口和抽象类有什么区别

    抽象类可能有也可能没有抽象方法 但接口仅具有未实现的方法 那么 如果我的抽象类将其所有方法都标记为抽象 那么使用接口有什么区别和优点呢 接口和抽象使用的真正威力可以在具有大量类的庞大 API 中体现出来 这些类遵循经过深思熟虑的灵活结构以供