在 PHP 中,"抽象类" 和 "接口" 有什么区别?
在 PHP 中,"抽象类" 和 "接口" 有什么区别?
这个问题已有答案:
可能重复:
据我所知,一个类实现或扩展抽象或接口类必须使用默认方法。我知道我们可以使用实现关键字来使用多个接口,但我们只能扩展1个抽象类。 在实际项目中使用哪一个,有什么区别?
admin 更改状态以发布 2023年5月24日
接口和抽象类的差异既有理论的,也有实际的:
- 接口是对类所具有和广告的某些能力的描述(因此,实现相同接口的各种类可以用相同的方式)。
- 抽象类可以是默认实现,包含可能出现在所有实现中的部分,它不需要实现完整的接口。
例如-一个接口:
// 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)将被传递,并且它们将如何完成目标,因为所有检索器都应该能够表现出类似的行为方式。您也可以使用抽象类来实现此操作,但是这会基于类祖先而限制自己,而不是其能力。