【问题标题】:Interfaces and abstract class inheritance, implementation in extended classes接口和抽象类继承,扩展类中的实现
【发布时间】:2011-09-16 04:23:06
【问题描述】:

在我见过的每个示例中,扩展类都实现了其父类的接口。作为参考,下面的例子:

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{}

未能在孩子中实现由父母实现的接口是否被认为是不好的做法或什么?在孩子中省略实施是否有任何技术缺陷?

【问题讨论】:

  • 那你没看我的例子
  • @Gordon - 不,先生,我没有。所以我假设你通常会从子类声明中省略接口。
  • 是的,完全正确。无论如何,孩子都会实现该接口。见codepad.org/OTZ2J5kB

标签: php inheritance interface abstract-class


【解决方案1】:

我认为你是在正确的道路上。在扩展已经implements 的类时,无需声明您正在实现该接口。对我来说,如果需要更改,这只是要维护的另一段代码。所以,是的,你是对的!

【讨论】:

  • 谢谢埃米尔·伊万诺夫;这就是我的假设。我对接口(超越 SPL 等)的工作不多,并开始将它们合并到我的项目中,因为越来越多的代码将被客户端程序员接触。我主要担心的是是否会因遗漏而对继承发生任何变化。
【解决方案2】:

未能在子代中实现由父代实现的接口是否被认为是不好的做法?

孩子总是实现接口,不能绕开这个。

我不知道这是不是不好的做法。我会说这是一种语言功能。

在子进程中省略实现是否存在任何技术缺陷?

例如,您不能测试抽象类的反射以获得接口。

但是,抽象类已经是一个接口,所以从技术上讲,它们本身并不真正需要该接口,但您可以这样做以保持继承内的流畅性。

【讨论】:

    【解决方案3】:

    是没有实现一个接口 在一个孩子中,这是由一个 父母,被认为是不良做法或 某物?有没有技术 省略的缺点 在孩子身上实施?

    我无法比这个人更好地回答你的问题:

    就其性质而言,虽然有时 它们可能看起来很相似,很抽象 类和类接口服务 非常明确的目的。

    类的接口意味着 该类的“用户”的工具。一个 界面是一个公开的演示文稿 该类,它应该做广告,以 任何人考虑使用它,什么 方法和常量可用 并可从外部访问。所以, 顾名思义,它总是坐在 用户和类之间 实现它。

    另一方面,抽象类 是一种旨在帮助 类的“实现者” 扩展它。它是一种基础设施 可以施加限制和 关于具体内容的指导方针 类应该看起来像。从一个班级 设计视角,抽象类 在架构上更重要 比接口。在这种情况下, 实现者位于抽象之间 类和具体的一类,建筑 后者在前者之上。

    Reference

    因此,您可以根据谁将使用(实例化)您的类以及谁将编写它们来决定。如果你是你的类的唯一用户和作者,那么,也许,只是也许,你不需要它们。但是,如果您想为每个人提供类编写者和类用户的核心位蓝图,那么您应该考虑同时使用抽象和实现。

    【讨论】:

      【解决方案4】:

      嗯,我也很困惑,但是我觉得你应该用后一种,你是对的,如果你在抽象类中实现了接口,那么就不需要写接口了,你可以把方法写在接口全部作为抽象方法抽象,因为您将扩展抽象类,并且当您在其他地方使用该类时,您必须将抽象类用作参数类型,这不是一件好事,我认为抽象类不应用作参数类型,而应用作接口。

      【讨论】:

        【解决方案5】:

        可能有点晚了,但我看到上述 cmets 并没有澄清 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.
            }
        
        }
        

        那么问题来了:

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

        答案:

        1. 由于 PHP 只允许对每个子类进行单一继承(你不能写 class MyConcreteClass extends MyAbstractClass, MyAnotherClass {}),当我们需要扩展已经使用的抽象类之外的具体类功能时,我们必须通过一个或更多接口。

          像这样:

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

        最后,回答 OP 问题是将接口用于抽象类还是具体类:

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

        【讨论】:

          猜你喜欢
          • 2011-11-03
          • 2018-04-05
          • 1970-01-01
          • 2012-04-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-21
          • 2012-07-15
          相关资源
          最近更新 更多