关于类:在PHP中抽象和接口有什么区别?

what's the difference between abstract and interface in php?

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

Possible Duplicate:
PHP: What is the difference between an interface and abstract class?

嗨,伙计们。

据我所知,clase实现或扩展抽象类或接口类必须使用默认方法。我知道我们可以使用implement关键字来使用多个接口,但是我们只能扩展1个抽象。有人能解释在现实生活项目中使用哪一个和它的区别吗?非常感谢!!!!!


这些差异既有理论上的,也有实践上的:

  • 接口是对类拥有的某些功能和广告的描述(因此实现同一接口的各种类可以以相同的方式使用)
  • 抽象类可以是默认实现,包含可能出现在所有实现中的部分。它不需要实现完整的接口

示例-接口:

1
2
3
4
5
6
7
8
9
10
11
// define what any class implementing this must be capable of
interface IRetrieveData {
    // retrieve the resource
    function fetch($url);

    // get the result of the retrieval (true on success, false otherwise)
    function getOperationResult();

    // what is this class called?
    function getMyClassName();
}

现在,我们有了一组需求,这些需求将针对每个实现这一点的类进行检查。让我们创建一个抽象类及其子类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// define default behavior for the children of this class
abstract class AbstractRetriever implements IRetrieveData {
    protected $result = false;

    // define here, so we don't need to define this in every implementation
    function getResult() {
       return $result;
    }

    // note we're not implementing the other two methods,
    // as this will be very different for each class.
}

class CurlRetriever extends AbstractRetriever {
     function fetch($url) {
         // (setup, config etc...)
         $out = curl_execute();
         $this->result = !(curl_error());
         return $out;
     }
     function getMyClassName() {
         return 'CurlRetriever is my name!';
     }
}

class PhpRetriever extends AbstractRetriever {
     function fetch($url) {
        $out = file_get_contents($url);
        $this->result = ($out !== FALSE);
        return $out;
     }
     function getMyClassName() {
         return 'PhpRetriever';
     }
}

一个完全不同的抽象类(与接口无关),具有实现接口的子类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
abstract class AbstractDog {
     function bark() {
         return 'Woof!';
     }
}

class GoldenRetriever extends AbstractDog implements IRetrieveData {
     // this class has a completely different implementation
     // than AbstractRetriever
     // so it doesn't make sense to extend AbstractRetriever
     // however, we need to implement all the methods of the interface
     private $hasFetched = false;

     function getResult() {
         return $this->hasFetched;
     }

     function fetch($url) {
         // (some retrieval code etc...)
         $this->hasFetched = true;
         return $response;
     }
     function getMyClassName() {
         return parent::bark();
     }
}

现在,在其他代码中,我们可以这样做:

1
2
3
function getStuff(IRetrieveData $retriever, $url) {
    $stuff = $retriever->fetch($url);
}

我们不必担心哪只猎犬(curl、php或golden)会被传进来,以及它们将如何完成目标,因为所有的猎犬都应该能够做出类似的行为。您也可以使用抽象类来实现这一点,但随后您将基于类的祖先而不是它的能力来限制自己。


多重继承与单一继承:

  • 只能从单个抽象类继承
  • 您可以实现多个接口

实施:

  • 抽象类实际上可以包含正在运行的代码。这允许您在子类之间共享实现
  • 接口只定义公共成员函数。实现相同接口的类实际上并不共享代码。

这就是我所知道的。


我听到的最好的比喻是抽象类是半成品类。还没完成,你还得完成。因此,当您创建一个扩展抽象类的类时,您只是完成了从抽象类开始的工作。这也是为什么你不能实例化一个抽象类的原因;你已经使它成为抽象的表明它是不完整的。它仍然需要一些额外的功能。

接口只是保证某些方法(每个方法都有一定数量的参数)必须存在于实现它的类中。因此,稍后,使用实现特定接口的类的程序员可以放心地调用该类上的某些方法。


下面是对这两种不同之处的很好描述:

http://www.supertom.com/code/php_abstracts_and_interfaces.html

归根结底,扩展是一种"IS-A"关系,而实现是一种"HAS-A"关系。


参见本页:5 PHP中抽象类和接口的主要区别

这个:相关的stackoverflow答案。


1
2
"An Abstract Class can contain default Implementation, where as an
Interface should not contain any implementation at all."

至于在现实世界中的应用…这真的取决于上下文。

例如,前几天这里有一个关于使用PHP实现游戏的问题。在这里,他们有一个定义怪物的抽象类,任何怪物都可以基于这个抽象类。这允许继承默认的怪物属性。

而对于一个接口,您定义了一个"接口"方法的一般要求(请原谅在解释中使用这个术语)一些系统。这是我最近做的一个项目的一个例子。我在PHP中实现了一个SoapClient,以便与来自第三方的SoapServer进行交互。此接口定义服务器支持哪些SOAP方法,因此实现我的接口的任何类都必须定义这些方法。