【转载】该用 Abstract Class 还是 Interface?
来源:互联网 发布:淘宝开网店的保证金 编辑:程序博客网 时间:2024/05/11 18:36
按三点答:
先答属性:抽象类可以有普通成员变量,接口不行;
然后答方法:抽象类有非抽象的方法和构造方法,并且修饰符可以是私有的,接口只能是抽象的方法,并且修饰符是public;
最后说一句只能继承一个抽象类,但能实现多个接口。
在编写程序的时候我常常陷入纠结,一个抽象对象,到底应该定义成 抽象类(Abstract Class) 还是 接口(Interface) 呢?二者具有很大的相似性,甚至可以相互替换,难以选择。在 Stackoverflow 上这个问题被问了很多次,各种编程语言的都有。而在 PHP 官网文档 Abstract Class 和 Interface 章节下面的评论里,人们也是争论不休。为了弄明白这个问题,必须仔细对比一下二者的区别和使用场景。
一、Abstract Class 与 Interface 的构造
抽象类 Abstract Class
- <?php
- abstract class A {
- abstract public function method1();
- abstract public function method2();
- public function method3() {
- //... code ...
- }
- }
- ?>
接口 Interface
- <?php
- interface B {
- public function method4();
- public function method5();
- }
- ?>
可以看到,Abstract Class 中可以有抽象函数(method1,method2),也可以有具体的函数实现(method3),而 Interface 中只能定义函数而不能有实现(method4,method5)。显然,如果一个抽象类中的函数全部是抽象函数,那么这个抽象类就退化成了接口。不过要注意的是
PHP 和 Java 一样,一个 Class 只能继承一个 Abstract Class,但可以实现多个 Interface。这即是所谓的单一继承体系,也就是子类别只能继承一个父类别;一个父类别则可以被多个子类别所继承。据说在 Python 中是可以多重继承的。
在 Abstract Class 中可以声明属性成员变量(attribute),而 Interface 不可以。
二、举例
下面的例子可以帮助我们从另一个层面:Abstract Class 和 Interface 所反映出的设计理念,来分析一下二者的本质区别。
假设我们要定义一个关于“门”的 Class,门有“开”和“关”两个动作。此时我们既可以用 Abstract Class 也可以用 Interface 来描述这个抽象概念——
抽象类 Abstract Class
- <?php
- abstract class Door {
- abstract public function open();
- abstract public function close();
- }
- ?>
接口 Interface
- <?php
- interface Door {
- public function open();
- public function close();
- }
- ?>
在 Abstract Class 中并没有实现开门和关门方法,因为有的门可以用钥匙打开,有的门用密码打开,还有的门可以用指纹打开,这些具体方法就交给子类继承去实现。在这样看上去 Abstract Class 和 Interface 二者的使用没有太大差别。
现在如果定义一种具有“报警”功能的门,Abstract Class 和 Interface 描述类似——
抽象类 Abstract Class
- <?php
- abstract class Door {
- abstract public function open();
- abstract public function close();
- abstract public function alarm();
- }
- class AlarmDoor extends Door {
- public function open() {
- //...
- }
- public function close() {
- //...
- }
- public function alarm() {
- //...
- }
- }
- ?>
接口 Interface
- <?php
- interface Door
- {
- public function open();
- public function close();
- public function alerm();
- }
- class AlarmDoor implements Door {
- public function open() {
- //...
- }
- public function close() {
- //...
- }
- public function alarm() {
- //...
- }
- }
- ?>
很明显上面的做法是不对的。它在定义中把 Door 本身固有的开门、关门的行为方法和另外一个概念“报警器”的行为方法混在了一起。有的门可以报警,而有的门可能没有报警功能;而会报警的门也可能多种多样(钥匙开门,刷卡开门等等)。我们必须将报警行为单独定义到另一个对象中,那么就有 3 种方式:
- 门和报警器都用 abstract class 方式定义;
- 门和报警器都用 interface 方式定义;
- 一个使用 abstract class 方式定义,另一个使用 interface 方式定义。
由于 PHP 中子类只可继承自一个 Abstract Class,而且 Abstract Class 不支持多重继承(abstract class cannot extend abstract class),所以第一种方式显然不行。而第二种方式则没有能够正确的揭示我们的设计意图,也就是没有反映出 AlarmDoor 在概念本质上是 Door,同时它有具有报警功能。所以对于 Door 这个概念,我们应该采取 Abstract Class 方式来定义,AlarmDoor 继承自 Door,而报警概念通过 Interface 方式定义。
- <?php
- abstract class Door {
- abstract function open();
- abstract function close();
- }
- interface Alarm {
- function alarm();
- }
- class AlarmDoor extends Door implements Alarm {
- public function open() {
- //...
- }
- public function close() {
- //...
- }
- public function alarm() {
- //...
- }
- }
- ?>
这样的实现基本上正确地反映了我们的设计意图。接口是可以多重继承的,子类也可以实现多个接口。这样就使得我们可以继续扩展门的功能,比如给门再装个摄像头……
三、结论
当我们使用 Abstract Class 的时候,我们应该定义一类对象的属性,即描述它 是什么。而 Interface 则类似于插件,侧重于提供附加的能力,约定它 能做什么。
- 【转载】该用 Abstract Class 还是 Interface?
- Abstract class VS Interface 转载
- 深入理解abstract class和interface【转载】
- 转载:深入理解abstract class和interface
- 深入理解abstract class和interface(转载)
- 是选择abstract class 还是选择 interface这是个问题
- abstract class和interface的区别(转载)
- abstract class和interface
- abstract class和interface
- Abstract class versus Interface
- abstract class和interface
- abstract class && Interface 比较
- Interface And Abstract Class
- Abstract class & Interface
- abstract class和interface
- abstract class和interface
- abstract class和interface
- Abstract class versus Interface
- Jquery三层实现删除功能
- 1128 分解质因数
- Qt状态机学习2
- 网卡MAC地址相关信息大全(整理)(上)
- 不要轻易受别人的影响
- 【转载】该用 Abstract Class 还是 Interface?
- POJ 3856 deltree
- fusionchats不能遮罩问题_hanCSDN_20130422
- Spring 配置事务管理说明
- 解决Ubuntu 12.04启动错误:Checking Battery State ..
- 工作中代码细节
- Jpivot + mondrian +xmla配置
- java、axis2、wsdl
- cocos2d-x之CCGUI设计与实现(1)序言