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

标签 php oop interface abstract-class

抽象类可能有也可能没有抽象方法,但接口(interface)只有未实现的方法。那么,如果我的抽象类的所有方法都标记为抽象,那么使用接口(interface)有什么区别和优势呢?

最佳答案

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

可以在没有接口(interface)的情况下创建小型 API,而这正是大多数人认为不需要接口(interface)的地方。但是一旦它们变大,它们就会失去灵 active 。他们为您提供类(class)契约(Contract),提醒您需要什么并保持概览。接口(interface)必须有公共(public)方法,如果你有保护或私有(private)方法,只需在实现接口(interface)的类的公共(public)方法中返回它们..

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

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

  • 界面代表了一系列可能性和要求。
  • 抽象保留与派生上下文相关的概念信息。

我将向您展示一个具有简化内容的 API 开头的典型结构,其中接口(interface)和抽象类具有用于 future 扩展的实际使用点。

/* 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 的模块一样。这种结构在适当的编码中具有语义过程。

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

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 ,维护 OOP 的最佳应用程序。

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

enter image description here

phUML 是 PHP 中基于 UML 的 API。它是一个开源项目,可以为几乎所有流行的编程语言生成任何视觉方案。我经常使用它,而不仅仅是用于 PHP。只需将其克隆到 Github 或从 下载 dasunhegoda.com 并按照那里的安装指南进行操作。
这可能会让您感兴趣: Typehinting on Interfaces

关于PHP - 如果抽象类中的所有方法都是抽象的,那么接口(interface)和抽象类之间有什么区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37437633/

相关文章:

php - 如何通过 href 将变量发送到路由并由 Controller 接收

php - 如何递归获取多维数组中所有父元素的ID?

oop - 在matlab中动态创建类

javascript - 如何在 JavaScript 中建模这个数据结构? (AngularJS)

interface - Racket:接口(interface)的前向声明

interface - Go 界面中的设计决策{}

php - Ckeditor/PHP 中的 WordPress 风格简码

php - 如何在具有多个数据库的 CodeIgniter 中存储数据库 session ?

java - 如何创建启动 Activity 的方法?

c++ - std::list 接口(interface)内存泄漏