php中的抽象和接口有什么区别?(复制)

时间:2020-12-19 22:28:07

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

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

hi guys..

嗨伙计们……

As far as I understand, a clase 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. Can anyone explain which one to use in real life project and the difference? Thanks a million!!!!

据我所知,clase实现或扩展抽象或接口类必须使用默认方法。我知道我们可以使用实现关键字来使用多个接口,但是我们只能扩展一个抽象。有人能解释一下在现实生活中使用哪一种吗?由于一百万年! ! ! !

6 个解决方案

#1


11  

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.

我们不需要担心将传入哪些回发(cURL、PHP或Golden),以及它们将如何实现目标,因为所有回发都应该具有类似的行为能力。您也可以使用抽象类来实现这一点,但是您将根据类的祖先(而不是它的功能)来限制自己。

#2


5  

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.

这就是我从头顶上知道的。

#3


2  

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.

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

#4


1  

See this page: 5 Main Difference between Abstract class and Interface in PHP

请参阅本页面:PHP中抽象类和接口的5个主要区别。

And this: related * answer.

这个:相关的*答案。

#5


1  

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

以下是对两者差异的一个很好的描述:

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

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.

这一切可以归结为这样一个事实:扩展是一种“is-a”关系,而实现是一种“has-a”关系。

#6


1  

"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.

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

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.

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

#1


11  

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.

我们不需要担心将传入哪些回发(cURL、PHP或Golden),以及它们将如何实现目标,因为所有回发都应该具有类似的行为能力。您也可以使用抽象类来实现这一点,但是您将根据类的祖先(而不是它的功能)来限制自己。

#2


5  

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.

这就是我从头顶上知道的。

#3


2  

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.

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

#4


1  

See this page: 5 Main Difference between Abstract class and Interface in PHP

请参阅本页面:PHP中抽象类和接口的5个主要区别。

And this: related * answer.

这个:相关的*答案。

#5


1  

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

以下是对两者差异的一个很好的描述:

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

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.

这一切可以归结为这样一个事实:扩展是一种“is-a”关系,而实现是一种“has-a”关系。

#6


1  

"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.

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

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.

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