PHP中的抽象类和接口是什么?何时使用它们?一个外行人回答一个例子对我的理解很有帮助。
答案 0 :(得分:7)
抽象类和接口不是特定于PHP的;它们是许多现代面向对象语言的特征。
抽象类是具有一个或多个未实现的成员函数的类。您可以在需要一组具有相似行为的类的情况下使用一个,仅在少数方法中有所不同。这些类中的每一个都派生自抽象类,并以适合其特定情况的方式实现未实现的方法。
接口类似于抽象类,但它不包含任何方法实现,只包含签名。实现接口的类必须实现所有方法。
一个类可以实现许多接口,但只能从一个抽象类(或任何类型的父类)派生,因为PHP不支持多重继承。
抽象类和接口都允许多态;即,您可以将引用指定为抽象类型(可以引用从中派生的类的任何实例)或实现接口的对象。
答案 1 :(得分:4)
假设您理解为何在其他语言中使用它们,则相同的概念适用于PHP。接口是类“签名”......它们不包含代码。抽象类不能实例化,但它们可以包含实现和抽象(空)函数。
请注意,类只能扩展单个父类(或抽象类),但它可以根据需要实现任意数量的接口。
但鉴于PHP没有严格的输入并且没有编译时间检查的概念,你可以通常不使用它们,这与C ++或Java等语言不同。
核心PHP需要某些东西的接口。例如:
class Foo implements Countable
{
public function count()
{
return 5;
}
}
echo count(new Foo()); // returns 5
如果删除“implements Countable”,PHP将不会调用您的count
方法。您可以实现许多其他接口,允许自定义对象以类似的方式运行。例如,您可以创建一个使用foreach
迭代的对象。
用户级别的接口在PHP中并不是非常有用,正如我之前提到的那样。但是如果你使用类型提示,它们可以是:
function foo(MyInterface $bar)
{
$bar->someMethod();
}
假设someMethod
中声明MyInterface
,则可以保证对$bar->someMethod()
的调用存在。 (之所以这在PHP中并不像在其他语言中那样有用,是因为函数签名中的类型提示在运行时才会被检查。)
空接口也可用作分类类的方法。假设您想对特定的一组对象执行某些操作。他们都可以实现一些空接口。然后你的代码可以检查该接口,而不必知道关于该对象的任何信息。
interface Red {}
class Foo implements Red { }
$foo = new Foo();
if ($foo instanceof Red)
{
// do something
}
当你有很多在子类之间共享的代码时,抽象类很有用,但它本身没有意义。您可以将基类声明为抽象,实现所有共享功能,并将其余功能保留为空。通过将基类声明为抽象,没有人能够自己使用它。
答案 2 :(得分:1)
PHP手册简单解释并提供了许多示例:
答案 3 :(得分:1)
答案 4 :(得分:0)
接口定义了一个类必须实现的一组方法。这样的类通过提供这些方法的具体实现来实现接口。接口不能包含自己的任何实现;它只是一组方法签名。如果我定义了一个名为ILogger
的接口,那么我可以编写使用ILogger
(可能是write
和writeLine
)中定义的方法的代码来传递要记录的消息。我可以传入任何实现ILogger
的类,并且它与客户端代码完全相同。
抽象类类似,但可以实现一些方法和状态。抽象类无法实例化,任何扩展它们的类都必须提供父类中每个abstract
方法的实现。如果一组类共享一些实现细节但在其他类中有所不同,那么您可以在抽象类中定义共享实现,声明不同的方法abstract,并让子类用自己的实现填充它们。如果我想要一种统一的方式来收集系统信息,添加我的所有记录器共享的时间戳等,我可能会选择创建一个处理这些细节的抽象类LoggerBase
,标记为write
和{ {1}} writeLine
以便任何扩展abstract
的类只需指定如何写入其特定日志。