接口和抽象类继承,扩展类中的实现

Dan*_*ugg 34 php inheritance abstract-class interface

在我看过的每个例子中,扩展类都实现了父类的接口.供参考,以下示例:

interface MyInterface{
    public function foo();
    public function bar();
}

abstract class MyAbstract implements MyInterface{
    public function foo(){ /* stuff */ }
    public function bar(){ /* stuff */ }
}

// what i usually see
class MyClass extends MyAbstract implements MyInterface{}

// what i'm curious about
class MyOtherClass extends MyAbstract{}
Run Code Online (Sandbox Code Playgroud)

是否未能在子级中实现接口,这是由父级实现的,被视为不良做法或其他什么?省略孩子的实施是否有任何技术缺陷?

Emi*_*nov 20

我会认为你走的是正确的道路.在扩展已经存在的类时,无需声明您正在实现接口implements.对我而言,如果需要进行更改,这只是另一段代码.所以,是的,你是对的!


She*_*hef 18

是否未能在子级中实现接口,这是由父级实现的,被视为不良做法或其他什么?省略孩子的实施是否有任何技术缺陷?

我只是不能比这家伙更好地回答你的问题:

就其性质而言,尽管有时它们看起来非常相似,但抽象类和类接口具有非常不同的用途.

类的接口意味着该类的"用户"的工具.接口是该类的公开演示,它应该向任何考虑使用它的人宣传哪些方法和常量可用并可从外部访问.因此,顾名思义,它始终位于用户和实现它的类之间.

另一方面,抽象类是一种旨在帮助扩展它的类的"实现者"的工具.它是一个基础设施,可以对具体类应该是什么样的实施限制和指导.从类设计的角度来看,抽象类在界面上比界面更重要.在这种情况下,实现者位于抽象类和具体类之间,将后者构建在前者之上.

参考

因此,由您来决定,根据谁将要使用(实例化)您的类,以及谁将要编写它们.如果您是班级的唯一用户和作者,那么,也许,只是也许,您不需要它们.但是,如果你想让每个人都被剥离到类编写器和类用户的核心位蓝图,那么你应该考虑使用抽象和实现.


Val*_*Shi 7

也许有点晚了,但我看到上述评论并没有澄清OP问题背后的主要误解。

所以根本的问题是:

  • 为什么我们在同一行上同时使用抽象类和接口?
  • 抽象方法和接口是否应该声明相同的方法?

但在澄清为什么要使用上述两者之一之前:

  • 其中任何一个都被一个程序员用来定义其他程序员在基于该程序员开发的抽象类/接口创建具体类(最终是整个软件应用程序)时必须遵守的契约(要求、义务、限制)。
  • 反过来,抽象类用于通过以下方式为后来创建的具体类提供方法和数据结构蓝图:

    1. 数据结构声明(可选),
    2. 方法的基本实现(及其签名,可选)
    3. 只是方法声明(类似于接口用法,可选)。
  • 接口用于通过以下方式提供带有方法蓝图的具体类

    1. 只是方法(及其签名,可选)声明。

这是抽象类和具体类的示例。

abstract class MyAbstractClass {

    public function foo() {
        // Base implementation of the method here.
    }

    public function bar() {
        // Base implementation of the method here.
    }

    // Effectively similar to baz() declaration within some interface:
    public abstract function baz($value);

}

class MyConcreteClass extends MyAbstractClass {

    // foo() and bar() are inherited here from MyAbstractClass.

    // baz() must be implemented or declared abstract again.
    public function baz($value) {
        // implementation.
    }

}
Run Code Online (Sandbox Code Playgroud)

那么问题来了:

  1. 为什么我们需要一个接口?
  2. 我们是否需要一个接口来重复相同的方法声明?

答案:

  1. 由于 PHP 只允许每个子类进行单一继承(您不能编写class MyConcreteClass extends MyAbstractClass, MyAnotherClass {}),因此当我们需要将具体类功能扩展到已使用的抽象类之外时,我们必须通过一个或多个接口声明这一附加功能。

    像这样:

    class MyConcreteClass 
        extends MyAbstractClass 
        implements MyInterface, MyAnotherInterface {
        // Methods and data implementations go here.
    }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 正如答案1的结果,接口最好不要重复抽象类方法的声明(这基本上是无用的)。接口应该声明可能有助于增强具体(或另一个抽象类,为什么不)功能的方法,以便为将使用这些方法的程序员提供构建在这些类和接口之上的每个对象的固定契约。

最后,对于抽象类还是具体类使用接口的OP问题的答案是:

  • 只要接口通过新方法的声明增强了类契约,即可用于其中之一或两者(或根据需要)。