摘要是指“这里有一个类的模板和一些可以让你开始的代码”。抽象类的设计者可以将某些方法标记为需要由扩展类提供(abstract
),或者标记为final
,这意味着该类不能覆盖它们。
接口是指“这里有一个类的模板,但你必须自己编写所有的代码”。在接口中声明的任何方法和属性必须由实现接口的类提供。
因此,一个经验法则是:
如果你有可以或必须被子类使用的代码,你需要一个抽象类。如果你只有方法和属性声明,你可以使用一个接口。
不要忘记,使用抽象类会在一定程度上限制你,因为一个子类只能扩展一个类,而它可以实现任意数量的接口。
接口就像一个合同。如果一个类实现了一个接口,使用这个类的其他代码现在知道它支持某些功能。
PHP中最好的接口示例是Iterator接口。
接口的好处是类可以实现多个接口。'扩展'不允许这样做。这意味着子类可以实现一个接口,但它的父类不必。
阅读设计模式。你会发现很多内容都有涉及,并且你再也不会怀疑什么情况下使用它是有意义的。我认为《Head first设计模式》是一本很好的书,写得非常好。虽然他们在例子中使用的是Java,但大部分内容在PHP中也是适用的。
我还有一个真实场景的例子。
我们的应用程序总是在出现错误时无处不在地抛出异常。每种类型的异常都有自己的自定义类。其中一个例子是RecordNotFound异常。
如果异常没有被捕获,就会有一个顶级异常块,它看起来有点像这样:
try {
// Do everything in the app!
} catch (Exception $e) {
// draw a good error page
}
interface HTTPException {
function getHTTPCode();
}
任何异常,无论在继承树中深度如何,现在都可以实现此接口并发出特定的HTTP状态码。
我甚至创建了没有任何方法的接口。我会留给你思考为什么这可能有意义。
接口是一个类的骨架结构,它本身不是一个类。我们可以实现该类并添加一些额外的特性以使其更加清晰。在接口中,可以使用implements关键字来实现。通常情况下,实现是用于接口实现功能的方式。
抽象是隐藏一些功能并仅显示必要功能的类。可以使用extend关键字来扩展抽象类。通常情况下,扩展用于扩展抽象类的功能。