长时间以来一直看到网上有断有人在讨论在面向对象设计中,抽象类和接口都可以作为“契约”的声明方式,可以被派生类 重写/实现,那么为什么在大多数的面向对象的语言中都同时保留了这两种类型呢,另外在什么样的情况下该使用哪种类型更好,更能体现设计人的真正思想呢?
在学C#的过程中,逐渐接触到了面向对象设计,我曾经对这个问题感到很迷惑,如果除了语言上限制的类的单继承和抽象类可以有部分实现这两点外——当然,这也是区分使用接口还是抽象类的一个条件,但只是次要的条件——那个时候还真区分不了两个有什么区别。只能从语言的定义上得到一些粗浅的认识
那个时候只是记得抽象类里可以有成员变量,可以有具体的方法实现,可以继承自另一个类,可以有私有成员,实现别的接口,一般类能做的事情,抽象类都可以实现;而接口只能有声明,如 方法,事件,属性(property)的声明,而且只能是公开的声明,接口也可以继承其它的接口,而且一次还可以继承一个或多个接口。两者的相同点都是不能被实例化,而且采用两种类型写出的代码很多情况下都符合面向对象的原则。例如遥控器我们既可以用RemoteControl作为抽象基类,也可以用IRemoteControlable作为接口来实现。也许那个时候对面向对象的理解还是刚刚入门,只是停留在表面现象吧,没有看到这两种方式刚好代表了设计者两种不同的侧重点,也就是说从设计上来讲是完全不同的思想。这个是仅仅从编程语言本身去抠类型之间的语法上的不同是完全不一样的。
后来,随着时间的增加,看的这方面的书多了,看过和编写过的代码也多了,在脑子里潜意识的对这个问题逐渐有了新的认识,只是没有想到归纳总结一下,前几天在网上偶然看到别人的面试题有提到这个,才想到自己是不是也需要再回过头来重新认识一下抽象类和接口两种类型。
先来说说抽象类,抽象类从本质上来说还是一个类,是现实中一系列有相同特性的对象的一个抽象,代表了"Is a ...."。抽象类用于部分实现一个类,再由用户按需求对其进行不同的扩展和完善;抽象类在组件的所有实现间提供通用的已实现功能;抽象类主要用于关系密切的对象,如 shape、rectangle、triangle、square;从量级上来讲,抽象类主要用于设计大的功能单元;
接口从本质上来讲是一种行为或特征上的契约,一个接口代表了一组行为的集合,一组特征上的集合,代表了“Can do....", "Is like ..."。接口只是定义一个行为的规范或规定;接口创建在大范围全异对象间使用的功能,具有该接口的类型互相间没有任何联系,但都具有相同的功能或特征;接口适合为不相关的类提供通用功能;接口用于设计小而简练的功能块;
以前面的RemoteControl抽象类和IRemoteControlable接口为例,该接口和抽象类里面都可以有OpenTV、CloseTV,ChangeChannel等功能,一个电视遥控器可以有这样的功能,一个带遥控功能的对讲机也可以有这样的功能,但电视遥控器和对讲机之间并没有什么其它的联系,除了两个都有遥控的功能外。这正是我前面所说的这两种方式刚好代表了设计者两种不同的侧重点。单拿对讲机来看,不管是有没有遥控功能,这部对讲机还是一部对讲机,可是遥控器呢,除去遥控的功能,那就什么也不是了。在这里把IRemoteControlable应用到遥控器的设计上还勉强说得过去,但是把RemoteControl抽象类用于对讲机类的设计上就根本说不过去了(前面提到的抽象类代表了"Is a...”, 对讲机还是对讲机,只是额外具有了有了遥控的功能,可不能因为从RemoteControl继承下来就变成了遥控器了。但是如果我们的科学进步了,以后有一种遥控器具有短距离通话的功能了,这样的话,就可以用一个具有ITalkable接口的人RemoteControl继承的类来表示了,因为本质上它还是叫一个遥控器,只是给它额外加了一个通话的功能而以。
抽象类和接口是编程语言中的两种定义抽象类的方式,它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概 念本质的理解、对于设计意图的反映是否正确、合理,因为它们表现了概念间的不同的关系(虽然都能够实现需求的功能)。这其实也是语言的一种的惯用法。
总结一下。说到底,一种编程语言的每个类型都是一类设计思想的语法上的对应,以前没有从编程思想上去找本质的问题,反而在语言上抠细节,真是有点本末倒置了。
在学C#的过程中,逐渐接触到了面向对象设计,我曾经对这个问题感到很迷惑,如果除了语言上限制的类的单继承和抽象类可以有部分实现这两点外——当然,这也是区分使用接口还是抽象类的一个条件,但只是次要的条件——那个时候还真区分不了两个有什么区别。只能从语言的定义上得到一些粗浅的认识
那个时候只是记得抽象类里可以有成员变量,可以有具体的方法实现,可以继承自另一个类,可以有私有成员,实现别的接口,一般类能做的事情,抽象类都可以实现;而接口只能有声明,如 方法,事件,属性(property)的声明,而且只能是公开的声明,接口也可以继承其它的接口,而且一次还可以继承一个或多个接口。两者的相同点都是不能被实例化,而且采用两种类型写出的代码很多情况下都符合面向对象的原则。例如遥控器我们既可以用RemoteControl作为抽象基类,也可以用IRemoteControlable作为接口来实现。也许那个时候对面向对象的理解还是刚刚入门,只是停留在表面现象吧,没有看到这两种方式刚好代表了设计者两种不同的侧重点,也就是说从设计上来讲是完全不同的思想。这个是仅仅从编程语言本身去抠类型之间的语法上的不同是完全不一样的。
后来,随着时间的增加,看的这方面的书多了,看过和编写过的代码也多了,在脑子里潜意识的对这个问题逐渐有了新的认识,只是没有想到归纳总结一下,前几天在网上偶然看到别人的面试题有提到这个,才想到自己是不是也需要再回过头来重新认识一下抽象类和接口两种类型。
先来说说抽象类,抽象类从本质上来说还是一个类,是现实中一系列有相同特性的对象的一个抽象,代表了"Is a ...."。抽象类用于部分实现一个类,再由用户按需求对其进行不同的扩展和完善;抽象类在组件的所有实现间提供通用的已实现功能;抽象类主要用于关系密切的对象,如 shape、rectangle、triangle、square;从量级上来讲,抽象类主要用于设计大的功能单元;
接口从本质上来讲是一种行为或特征上的契约,一个接口代表了一组行为的集合,一组特征上的集合,代表了“Can do....", "Is like ..."。接口只是定义一个行为的规范或规定;接口创建在大范围全异对象间使用的功能,具有该接口的类型互相间没有任何联系,但都具有相同的功能或特征;接口适合为不相关的类提供通用功能;接口用于设计小而简练的功能块;
以前面的RemoteControl抽象类和IRemoteControlable接口为例,该接口和抽象类里面都可以有OpenTV、CloseTV,ChangeChannel等功能,一个电视遥控器可以有这样的功能,一个带遥控功能的对讲机也可以有这样的功能,但电视遥控器和对讲机之间并没有什么其它的联系,除了两个都有遥控的功能外。这正是我前面所说的这两种方式刚好代表了设计者两种不同的侧重点。单拿对讲机来看,不管是有没有遥控功能,这部对讲机还是一部对讲机,可是遥控器呢,除去遥控的功能,那就什么也不是了。在这里把IRemoteControlable应用到遥控器的设计上还勉强说得过去,但是把RemoteControl抽象类用于对讲机类的设计上就根本说不过去了(前面提到的抽象类代表了"Is a...”, 对讲机还是对讲机,只是额外具有了有了遥控的功能,可不能因为从RemoteControl继承下来就变成了遥控器了。但是如果我们的科学进步了,以后有一种遥控器具有短距离通话的功能了,这样的话,就可以用一个具有ITalkable接口的人RemoteControl继承的类来表示了,因为本质上它还是叫一个遥控器,只是给它额外加了一个通话的功能而以。
抽象类和接口是编程语言中的两种定义抽象类的方式,它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概 念本质的理解、对于设计意图的反映是否正确、合理,因为它们表现了概念间的不同的关系(虽然都能够实现需求的功能)。这其实也是语言的一种的惯用法。
总结一下。说到底,一种编程语言的每个类型都是一类设计思想的语法上的对应,以前没有从编程思想上去找本质的问题,反而在语言上抠细节,真是有点本末倒置了。
工作五年,长期从事于asp.net方面的编程,业余爱好VC编程,温和、谦虚、自律、自信、善于与人交往沟通