php中的抽象和接口有什么区别?

发布于 2024-09-16 13:43:13 字数 304 浏览 5 评论 0原文

可能的重复:
PHP:接口和抽象类之间有什么区别抽象类?

据我了解,实现或扩展抽象或接口类的类必须使用默认方法。我知道我们可以使用implement关键字来使用多个接口,但我们只能扩展1个抽象。在实际项目中使用哪一种以及有何区别?

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

As far as I understand, a class implements or extends abstract or interface class has to use the default methods. I know we can use implement keyword to use multiple interfaces, but we only can extend 1 abstract. Which one to use in real life project and the difference?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

凑诗 2024-09-23 13:43:13

理论上和实践上的差异都是不同的:

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

示例 - 接口:

// 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();
}

现在我们有了一组要求,将对每个实现此接口的类进行检查。让我们创建一个抽象类及其子类:

// 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';
     }
}

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

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();
     }
}

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

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

并且我们不必担心哪个检索器(cURL、PHP 或 Golden)将被传入,以及它们将如何实现目标,因为所有检索器都应该具有类似的行为。您也可以使用抽象类来做到这一点,但是您会根据类的祖先而不是其功能来限制自己。

The differences are both theoretical and practical:

  • interface is a description of some capability your class has and advertises (so various classes implementing the same interface can be used the same way)
  • abstract class can be a default implementation, containing the parts which are likely to appear in all the implementations. It doesn't have to implement the complete interface

Example - an interface:

// 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();
}

Now we have the set of requirements that will be checked for every class implementing this. Let's make an abstract class and its children:

// 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';
     }
}

A completely different abstract class (unrelated to the interface), with a subclass which implements our interface:

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();
     }
}

Now, in other code, we can do this:

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

and we don't have to worry which of the retrievers (cURL, PHP, or Golden) will be passed in, and how are they going to accomplish the goal, as all should be capable of behaving similarly. You could do this with an abstract class, too, but then you're restricting yourself based on the classes' ancestor, instead of its capability.

时光瘦了 2024-09-23 13:43:13

多重继承与单一继承:

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

实现:

  • 抽象类实际上可以在其中包含功能代码。这使您可以在子类之间共享实现
  • 。接口仅定义公共成员函数。实现相同接口的类实际上并不共享代码。

这就是我头脑中所知道的。

Multiple vs. single inheritance:

  • You can only inherit from a single abstract class
  • You can implement multiple interfaces

Implementation:

  • An abstract class can actually have functioning code in it. This lets you share implementation between the child classes
  • An interface only defines public member functions. Classes implementing the same interface don't actually share code.

That's what I know off the top of my head.

白日梦 2024-09-23 13:43:13

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

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

The metaphor I heard best was that an abstract class is a half-completed class. It's not done; you still have to finish it. So when you make a class that extends an abstract class, you are just completing what you began in the abstract class. This is also why you can't instantiate an abstract class; that you've made it abstract indicates that it's incomplete. It still needs some additional functionality.

An an interface just guarantees that certain methods, each with a certain number of arguments, must exist within a class that implements it. So that later on, a programmer who uses a class that implements a particular interface can rest assured that they can call certain methods on that class.

随心而道 2024-09-23 13:43:13

以下是对两者之间差异的详细描述:

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

这一切都归结为这样一个事实:extends 是一种“is-a”关系,而implements 是一种“has-a”关系。

Here's a good description of the differences between the two:

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

It all boils down to the fact that extends is a "is-a" relationship while implements is a "has-a" relationship.

飘落散花 2024-09-23 13:43:13
"An Abstract Class can contain default Implementation, where as an 
Interface should not contain any implementation at all. "

至于在现实世界的应用程序中使用哪个......这实际上取决于上下文。

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

而对于接口,您正在定义“接口”(请原谅在解释中使用该术语)某些系统的方式的一般要求。我最近做的一个项目就是一个例子。我在 php 中实现了一个soapclient,用于与第三方的soapserver 进行交互。该接口定义了服务器支持哪些soap 方法,因此任何实现我的接口的类都必须定义这些方法。

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

As far as which to use in real world application... it really comes down to context.

For example, there was a question on here the other day about implementing a game using PHP. Here they had a abstract class defining a monster and any monster could be based off of this abstract class. This allowed for inheritance of default monster properties.

Whereas for an interface, you are defining a general requirements for a way to "interface" (pardon using the term in the explanation) some system. An example of this from a recent project I did. I implemented a soapclient in php to interact with a soapserver from a third party. This interface defines what soap methods the server supports and thus any class implementing my interface must define those methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文