简体   繁体   English

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

[英]PHP - if all methods in abstract class are abstract then what is the difference between interface and abstract class

An Abstract Class may and may not have abstract methods but an interface has unimplemented methods only. 抽象类可能有也可能没有抽象方法,但接口只有未实现的方法。 So what is the difference and advantage of using an interface if my abstract class has all of its methods marked as abstract? 那么,如果我的抽象类将其所有方法标记为抽象,那么使用接口的区别和优势是什么?

Interfaces and Abstraction 接口和抽象
The real power of use can be revealed in huge APIs with massive amount of classes that follow a well-thought flexible structure for future coding. 真正的使用能力可以在庞大的API中体现出来,其中包含大量的类,这些类遵循经过深思熟虑的灵活结构,以便将来编码。 Whether it may happen or not - you never know whether a code will be extended. 是否可能发生 - 您永远不知道代码是否会被扩展。 Interfaces are merely used for semantic reasons. 接口仅用于语义原因。 Imagine, you extend a deprecated version of an API and have the job to edit/alter/implement/update/improve/extend/modify the code to bring it up to date, whatever the reason is. 想象一下,您扩展了一个已弃用的API版本,并且可以编辑/更改/实现/更新/改进/扩展/修改代码以使其更新,无论原因是什么。 You'd end up being frustrated if you did not think forward. 如果你没有想到,你最终会感到沮丧。

Small APIs can be made without the interfaces and that's where most people think interfaces were unnecessary. 可以在没有接口的情况下制作小型API,这也是大多数人认为接口不必要的地方。 But then they lose their flexibility as soon as they become larger. 但是一旦它们变大,它们就会失去灵活性。 They provide you a contract with classes which reminds you what is needed and to keep the overview. 他们为您提供课程合同,提醒您需要什么并保持概述。 Interfaces must have public methods, if you have protected or private ones, just return them in a public method of a class with interface implemented.. 接口必须有公共方法,如果你有保护或私有方法,只需在实现接口的类的公共方法中返回它们。

Like you already explained, interfaces demand particular methods to be implemented, abstract classes don't demand it since you most likely extend them anyway. 就像你已经解释过的那样,接口需要实现特定的方法,抽象类不要求它,因为你最有可能扩展它们。 Methods can be re-defined and abstract methods MUST be defined in child classes. 可以重新定义方法,并且必须在子类中定义抽象方法。 Methods mentioned in an interface only tells you that classes that have a contract with an interface must have these defined. 接口中提到的方法仅告诉您与接口签订合同的类必须具有这些定义的类。 It could be multiple interfaces, you don't inherit from them like you would do it with abstract classes. 它可以是多个接口,您不会像使用抽象类那样继承它们。

Think like this way 这样想
The logic in it is to predict the future in what you are planning to build. 其中的逻辑是预测您计划构建的未来。 Be it in architecture, infrastructure or mass production in factories. 无论是建筑,基础设施还是工厂的大规模生产。 Just like the way you sort items like bookmarks, books, images in a folder. 就像您对书签,书籍,文件夹中的图像等项目进行排序一样。 Because you know it would take longer to find a particular image if you didn't sort it. 因为您知道如果您没有对其进行排序,则需要更长时间才能找到特定图像。 The semantic purpose of abstraction and interface is similar, especially in huge APIs. 抽象和接口的语义目的是类似的,尤其是在大型API中。

  • An interface reperesents a frame of possibilities and requirements. 界面重现了可能性和要求的框架。
  • An abstraction preserves conceptual information that is relevant in a derived context. 抽象保留了在派生上下文中相关的概念信息。

I'll show you a typical structure for a start of an API with simplified contents wherein interfaces and abstract classes have a real point of usage for future extension. 我将向您展示一个具有简化内容的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);

Conclusion 结论
Applying styles of text contents as an example is probably not appealing enough. 应用文本内容的样式作为示例可能不够吸引人。 But apart from this, it remains the same - if it does what it should do, then it's done. 但除此之外,它仍然是相同的 - 如果它做它应该做的事情,那么就完成了。 Like as if I would build an expandable eMail configuration API as a module for a CMS. 就像我将构建可扩展的eMail配置API作为CMS的模块一样。 This structure has a semantic process in proper coding. 该结构在正确编码中具有语义过程。

Tipps 的窍门
I'd suggest you to keep learning in small projects with this pattern, even if you think interfaces are not worth it. 我建议你继续学习这种模式的小项目,即使你认为接口不值得。 Keep doing this until you have it inside. 继续这样做,直到你把它放进去。 My own personal advice for you: If you think you have no idea where to start and what project to try it on, then try real world examples just follow this logic: 我个人对你的建议:如果你认为你不知道从哪里开始以及尝试什么项目,那么试试现实世界的例子就是遵循这个逻辑:

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...

Usually, classes containing huge bodies are supposed to be separated in single files + include these + define a namespace. 通常,包含巨大主体的类应该在单个文件中分开+包括这些+定义命名空间。 Else wall of code would make you or someone else tired. 否则代码墙会让你或其他人感到厌倦。 Use Eclipse , best app for maintaining OOP. 使用Eclipse ,最好的应用程序来维护OOP。

Also, if it fits for your project, use phUML if you have Linux Ubuntu . 此外,如果它适合您的项目,如果您有Linux Ubuntu ,请使用phUML It generates a graphical diagram for your current build if you have a lot of relating classes. 如果您有很多相关类,它会为您当前的构建生成一个图形图表。

在此输入图像描述

phUML is an API in PHP based on UML. phUML是基于UML的PHP​​ API。 It is an open-source project which generates any visual schemes for almost any popular programming language. 它是一个开源项目,可以为几乎任何流行的编程语言生成任何可视化方案。 I use it a lot, not just for PHP. 我经常使用它,而不仅仅是PHP。 Simply clone it at Github or download from dasunhegoda.com and follow installation guide there. 只需在Github上克隆它,或从dasunhegoda.com下载并按照安装指南进行操作。
This could interest you also: Typehinting on Interfaces 您也会对此感兴趣: 在接口上进行类型设置

An Abstract Class allows for "partial implementation" (see the template method pattern), but in this case, if all methods are abstract, you don't see that benefit. 抽象类允许“部分实现”(参见模板方法模式),但在这种情况下,如果所有方法都是抽象的,那么您看不到这种好处。 One other thing you can do is include fields, you're not just limited to methods. 您可以做的另一件事是包括字段,您不仅限于方法。

Remember, there's a conceptual difference between an "abstract method" and the contract defined by an interface. 请记住,“抽象方法”与接口定义的契约之间存在概念上的区别。 An abstract method has to be overridden by a subclass which is done through inheritence implementation. 抽象方法必须由子类覆盖,该子类通过继承实现来完成。 Any polymorphic calls (downcasting) will require one superclass per class or it would hit the diamond inheritance problem. 任何多态调用(向下转换)都需要每个类一个超类,否则会遇到钻石继承问题。 This kind of inheritence based tree structure is typical of OO design. 这种基于继承的树结构是OO设计的典型。

As a contrast, an interface provides a signature of a contract to fulfil. 相比之下,界面提供了履行契约的签名。 You can fulfil many interface's needs as long as you retain the signature as there is no question of going back up the class hierarchy to find other implementations. 只要保留签名,就可以满足许多接口的需求,因为不存在返回类层次结构以查找其他实现的问题。 Interfaces don't really rely on polymorphism to do this, it's based on a contract. 接口实际上并不依赖于多态来实现这一点,而是基于契约。

The other thing of note is you may have "protected" abstract methods, it makes no sense to do such a thing in an interface (in fact it's illegal to do so). 另外需要注意的是,你可能有“受保护”的抽象方法,在接口中做这样的事情是没有意义的(实际上这样做是违法的)。

If an abstract class has all of its methods defined as abstract then you have to define its body in any subclasses and it displays similar behavior as interface . 如果abstract class将其所有方法定义为abstract则必须在任何子类中定义其主体,并且它显示与interface类似的行为。

Benefit : 好处:

Using interface instead of abstract class, you can implement more than one interfaces while using abstract class you can only extend one class at a time. 使用interface而不是abstract类,您可以在使用abstract类时implement多个interfaces ,一次只能扩展one类。

EDIT 编辑

Another difference I found about this is abstract class can have constructor while interface can't have. 我发现的另一个区别是abstract类可以有constructorinterface不能有。

REF: What is the use of constructor in abstract class in php REF: php中抽象类中构造函数的用法是什么

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM