接口和抽象
使用的真正威力可以在具有大量类的庞大 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/