2

这个问题听起来很明显,也可能很愚蠢。但我想弄清楚为什么我需要使用接口?我想我可以处理接口使用类所做的大部分事情,那么使用它们有什么意义呢?确实,如果我不使用接口,我可能会遇到问题,但我想弄清楚不使用接口会导致什么问题?

接口的一种用途是它们允许我们定义行为并对实现它们的类施加限制。

另一个用途是接口作为类型工作,我可以使用接口进行类型提示,如下所示。

//Java example
public interface IPaintable{
   void Paint(System.Drawing.Color color);
}

public void Paint(IPaintable item, System.Drawing.Color color){
   item.Paint(color);
}

但是 PHP 中接口还有其他用途吗?

即在下面的代码中使用接口可以获得什么好处。

//Non interface implementation
    <?php
    class DBPersonProvider
    {
        public function getPerson($givenName, $familyName)
        {
            /* go to the database, get the person... */
            $person = new Person();
            $person->setPrefix("Mr.");
            $person->setGivenName("John");
            return $person;
        }
    }

    /* I need to get person data... */
    $provider = new DBPersonProvider();
    $person = $provider->getPerson("John", "Doe");

    echo($person->getPrefix());
    echo($person->getGivenName());

    ?>

    //Implementation with interface

        <?php
        interface PersonProvider
        {
            public function getPerson($givenName, $familyName);
        }

        class DBPersonProvider implements PersonProvider 
        {
            public function getPerson($givenName, $familyName)
            {
            /* pretend to go to the database, get the person... */
            $person = new Person();
            $person->setPrefix("Mr.");
            $person->setGivenName("John");
            return $person;
        }
    }


    /* I need to get person data... */
   $provider = new DBPersonProvider();
    $person = $provider->getPerson("John", "Doe");

    echo($person->getPrefix());
    echo($person->getGivenName());
    ?> 
4

3 回答 3

1

我编写了一个与数据库交互的好库。我用MySQL. 当您购买我的库时,您知道它是MySQL基于的,但您使用SQL Server. 我很体贴地为数据库访问创建接口。我提供了一个实现MySQL。现在您可以围绕我的数据库访问接口实现自己的SQL Server包装器,然后将其用作__construct()库中类的参数,您将使用该类将移动存储更改为SQL Server.

接口对于像我这样的库/可重用代码编写者非常有用:)它们是必须遵守的代码契约。您知道任何实现它们的类都将具有一组与接口声明它们完全相同的函数。您还可以在函数参数中静态键入它们,例如function(MyInterface $Object)在 PHP 编译器级别强制执行,$Object必须实现MyInterface.

PS抽象类对于其他使用自写代码的开发人员来说已经足够好了......

更新

/**
* Database Access functionality blueprint.
*/
interface IDatabaseAccess {
    public function Connect();
    public function Query();
    public function Fetch();
}

/**
* Database Access functionality implementation for MySQL.
*/
class MySqlDatabaseAccess implements IDatabaseAccess {
    public function Query(){
        // do mysql stuff
    }
    public function Fetch(){
        // do mysql stuff
    }
}

/**
* Database Access functionality implementation for SQLServer.
*/
class SqlServerDatabaseAccess implements IDatabaseAccess {
    public function Query(){
        // do sqlserver stuff
    }
    public function Fetch(){
        // do sqlserver stuff
    }
}

/**
* Database Access consumer that's database system agnostic.
*/
class DatabaseAccessConsumer {
    protected $_Provider = null;
    public function __construct(IDatabaseAccess $Provider){
        $this->_Provider = $Provider;
        $this->_Provider->Connect();
    }
    public function Query(){
        return $this->_Provider->Query();
    }
    public function Fetch(){
        return $this->_Provider->Fetch();
    }
}

^应该为自己说话的代码

于 2013-07-16T14:15:15.210 回答
1

接口实际上提供的功能比抽象类少(你不能实现任何东西)。

但是它们解决了多重继承的问题。大多数现代语言不允许一个类派生多个类。通过使用不实现任何方法的接口,您可以确保从接口调用方法时没有歧义(因为没有实现)。

示例(语法无效):

class A {
    public foo() {
        echo 'I am A and I foo';
    };
    public 
}

class B {
    public foo() {
        echo 'I am B and I foo';
    }
}

class C extends A, B { // invalid
    public bar() {
        foo(); // which one? A's or B's?
    }
}

第二个例子:

class A {
    public foo() {
        echo 'I am A and I foo';
    };
}

interface iB {
    public foo();
    public bar();
}

interface iC {
    public foo();
    public qux();
}

class D extends A implements iB, iC {

    public bar() {
         foo(); // no ambiguity, this is A::foo(), even if the method is also declared in the interfaces
    }

    public qux() {}
}
于 2013-07-16T14:15:27.283 回答
1

接口只是类的蓝图——它们是说“如果你要对这种类型的类做某事,它必须有这个并做到这一点”的方式。它允许您在一定程度上控制另一个班级在给定情况下至少将拥有/做什么。并非每种情况都需要一个接口。当您需要对某些类的基本代码进行一些控制但您可能不是编写它们的人时,最好使用接口。如果您知道扩展类将具有 x 属性和 y 方法,那么您可以做基本的未来类支持。

于 2013-07-16T14:20:37.167 回答