与界面交互?

时间:2010-04-23 09:15:03

标签: php oop

从我所看到的,似乎可以与界面进行交互?

例如。让我说我有一个空方法接口“吃()”

然后有2个子类正在实现这个接口。

我的控制器可以只与界面交互并使用它的eat()方法吗?

查看此链接strategy

中的图片

1 个答案:

答案 0 :(得分:15)

除了访问接口中的任何已定义常量或将其用于TypeHints之外,您无法与接口进行交互。接口没有方法体。它们仅用于定义实现类必须遵守的合同。

interface Logger
{
    const FOO = 1;
    public function log($msg);
}

echo Logger::FOO;  // 1
Logger::log($msg); // Fatal error: Cannot call abstract method Logger::log()
new Logger;        // Fatal error: Cannot instantiate interface Logger

请参阅http://php.net/manual/en/language.oop5.interfaces.php


对接口进行编码 与接口进行交互时通常意味着什么只不过是调用中定义的方法 实现它们的类中的接口。您调用实现,而不是定义。该定义仅指定对于实现接口的每个Class,必须有一个具有指定参数的特定方法。

考虑这些课程:

Class DbLog implements Logger 
{
    public function log($msg) { /* log $msg to database */ }
}

Class FileLog implements Logger
{
    public function log($msg) { /* log $msg to file */ }
}

两个类都实现Logger,因此必须有方法log($msg)。你基本上是在说:“嘿,如果你想成为Logger,请确保我可以在你身上调用log()。”。现在代码中的某个地方可能有一个需要记录器的类,比如

class Foo
{
    protected $logger;
    public function __construct(Logger $logger)
    {
        $this->logger = $logger;
        $this->logger->log('I can haz logger! Yay!');
    }
}

Foo并不关心它是FileLogDbLog还是其他任何具体记录器。它只关心它能够任何 Logger它可以调用log()。 Foo甚至对log()所做的事情都不感兴趣。 Foo所关注的所有人都可以致电log()。你不是在界面中调用log()。您在传递给Foo的conrete类中调用它,但在UML图中,您表示它就像在您链接的页面中显示的那样,因为您只是针对接口进行编码

这样做的主要优点是你的课程耦合得更少。您可以更轻松地交换依赖关系,例如在单元测试中使用Mocks时,您的代码将更易于维护。

基本上,将接口视为概念标准化。例如,当你购买一台新的DVD播放器时,你希望它有一个按钮,以某种方式(你不关心如何,只是这样)使播放器播放DVD。当你按下那个按钮时,你没有按下DVD播放器必须有播放按钮的一般抽象DVD接口规范,但你点击了这个品牌播放器上播放按钮的具体实现。