【问题标题】:When are object interfaces useful in PHP? [duplicate]什么时候对象接口在 PHP 中有用? [复制]
【发布时间】:2011-06-10 23:51:02
【问题描述】:

来自php.net

对象接口允许您创建指定哪些方法的代码 一个类必须实现,而不必定义如何处理这些方法。

为什么我需要这样做?会不会是一种“文档”?

当我考虑我必须实现的类时,我确切地知道我应该编写哪些方法。

在哪些情况下接口类是“最佳实践”?

【问题讨论】:

标签: class language-agnostic interface


【解决方案1】:

简答:统一接口和多态性。

更长的答案:您显然可以创建一个可以执行所有操作的类,并且您确实知道要编写哪些方法。然而,只使用具体类的问题是你缺乏改变的能力。假设您有一个将用户存储到 MySQL 数据库中的类,我们称之为 UserRepository。想象一下下面的代码:

<?php
class UserRepositoryMysql {
    public function save( User $user ) {
        // save the user.
    }
}

class Client {
    public function __construct( UserRepositoryMysql $repos ) {
        $this->repos = $repos;
    }

    public function save( User $user ) {
       $this->repos->save( $user );
    }
}

现在,这一切都很好,因为它确实可以工作,并将用户保存到数据库中。但是想象一下你的应用程序会变得流行,很快就会出现支持 PostgreSQL 的问题。您必须编写一个 UserRepositoryPostgresql 类,并传递它而不是 UserRepositoryMysql。现在,您已经在 UserRepositoryMysql 上输入了提示,而且您不确定两个存储库使用相同的方法。顺便说一句,对于潜在的新开发人员来说,关于如何实现自己的存储的文档很少。

当您将 Client 类重写为依赖于接口而不是具体类时,您将可以选择“将它们替换掉”。这就是为什么接口在正确应用时很有用的原因。

【讨论】:

    【解决方案2】:

    首先,我的 php 对象编码远远落后于我的 .net 编码,但是,原理是相同的。在你的类中使用接口的好处是多方面的。以您需要从搜索例程返回数据的情况为例。此搜索例程可能必须在具有完全不同数据结构的许多不同类中工作。在“正常”编码中,试图结合各种不同的返回值将是一场噩梦。

    通过实现接口,您可以向使用它们的类添加责任来生成一组统一的数据,无论它们有多么不同。另一个示例是您从不同的“提供者”(例如 xml、json、csv 等)提取数据的情况。通过在每个类类型上实现一个接口,您可以通过添加实现该接口的新类来轻松扩展您的数据馈送,而不是通过混合 switch 语句来试图弄清楚您的意图是什么。

    总之,将接口视为类“必须”遵守的“契约”。知道这意味着您可以放心地为给定的场景编写代码,而只是实现细节有所不同。

    希望这会有所帮助。

    [edit] - 请参阅 SO 上的这个示例以获得相当简单的解释:

    接口是面向对象编程中的一个概念,它支持多态性。基本上,接口就像一个契约,实现它的类同意提供某些功能,以便可以像使用接口的其他类一样使用它们

    purpose of interface in classes

    【讨论】:

      【解决方案3】:

      我想到的第一个例子是当你有一个类使用另一个类的某些方法时。你不关心第二个类是如何工作的,但希望它有特定的方法。

      例子:

      interface IB {
          public function foo();
      }
      
      class B implements IB {
          public function foo() {
              echo "foo";
          }
      } 
      
      class A {
          private $b;
          public function __construct( IB $b ) {
              $this->b = $b;
          }
      
          public function bar() {
              $this->b->foo();
          }
      }
      
      $a = new A( new B() );
      $a->bar(); // echos foo
      

      现在您可以轻松地使用不同的对象传递给 A 类的实例:

      class C implements IB {
          public function foo() {
              echo "baz";
          }
      }
      
      $a = new A( new C() );
      $a->bar(); // echos baz
      

      请注意调用的是同一个 bar 方法。

      您可以使用继承实现类似的结果,但由于 PHP 不支持多重继承,接口更好 - 类可以实现多个接口。

      您可以查看PHP design patterns - Strategy 之一。

      【讨论】:

        【解决方案4】:

        假设您正在创建一个数据库抽象层。您提供一个 DAL 对象,该对象提供用于与数据库交互的通用方法以及将这些方法转换为特定数据库的特定命令的适配器类。这些适配器本身需要有一个通用接口,这样 DAL 对象才能以标准化的方式与它们通信。

        您可以使用接口指定适配器需要具有的接口。当然,您可以简单地编写一些文档来指定适配器需要具有哪些方法,但是用代码编写它可以让 PHP 为您强制执行此接口。它使 PHP 能够在执行单行代码之前抛出有用的错误消息。否则只有在运行时并且只有在您真正尝试调用它们时才能找到丢失的方法,这使得调试更加困难并且代码更加不可靠。

        【讨论】:

          猜你喜欢
          • 2013-10-19
          • 2017-04-15
          • 1970-01-01
          • 2012-12-13
          • 1970-01-01
          • 1970-01-01
          • 2012-01-05
          • 1970-01-01
          • 2011-09-24
          相关资源
          最近更新 更多