关于类:对象接口在PHP中什么时候有用?

When are object interfaces useful in PHP?

本问题已经有最佳答案,请猛点这里访问。

来自PHP.NET:

Object interfaces allow you to create code which specifies which methods
a class must implement, without having to define how these methods are handled.

我为什么要这样做?它可以是一种"文档"吗?

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

在什么情况下,将课堂互动作为"最佳实践"?


简短的回答:统一的界面和多态性。

更长的答案:显然,您可以创建一个完成所有工作的类,实际上您知道要编写什么方法。但是,您只使用具体的类的问题是您缺乏更改的能力。假设您有一个类将您的用户存储到一个MySQL数据库中,我们将其称为用户存储库。想象一下下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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。现在,您已经在userrepositorymysql上输入了提示,而且您不确定两个存储库使用相同的方法。顺便提一句,对于一个潜在的新开发人员来说,关于如何实现自己的存储,几乎没有文档。

当您重写客户机类以依赖于一个接口,而不是具体的类时,您将有一个"交换它们"的选项。这就是为什么接口在正确应用时显然是有用的。


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

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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实例的不同对象:

1
2
3
4
5
6
7
8
class C implements IB {
    public function foo() {
        echo"baz";
    }
}

$a = new A( new C() );
$a->bar(); // echos baz

请注意,调用了相同的bar方法。

使用继承可以获得类似的结果,但是由于PHP不支持多个继承,所以接口更好——类可以实现多个接口。

您可以查看其中一个PHP设计模式-策略。


首先,我的PHP对象编码远远落后于我的.NET编码,但是原理是相同的。在类中使用接口的好处有很多。例如,您需要从搜索例程返回数据。这个搜索例程可能必须在具有完全不同数据结构的许多不同类之间工作。在"正常"编码中,这将是一个噩梦,试图将不同的返回值结合起来。

通过实现接口,您可以向使用它们来生成统一数据集的CLSSE添加责任,不管它们有多不同。另一个例子是从不同的"提供者"(例如XML、JSON、CSV等)中提取数据。通过在每个类类型上实现一个接口,您可以通过添加实现接口的新类,而不是将开关语句混合在一起,试图弄清楚您的意图,从而轻松地扩展数据馈送。

总之,把接口看作是类"必须"遵守的"契约"。这意味着您可以在只改变实现细节的情况下,自信地为给定的场景编写代码。

希望这有帮助。

[编辑]-有关相当简单的解释,请参阅下面的示例:

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

类中接口的用途


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

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