继承是一个非常有用的概念,但是却很容易被用得不合适,通常用接口来实现可能会更好,本文的目的就是使用户懂得怎样更好的使用类的继承。
当遇到如下情况时,继承将是一个好的选择:
(1)简化一个低等级的不使用类的API函数
(2)从基本类中得到重用的代码
(3)需要对不同的数据类型使用相同名称的类和方法
(4)类的层次相当,最多4到5级,而且不仅增加一级或两级
(5)通过改变一个基本类,就改变所有的派生类。
1.简化一个低等级的不使用类的API函数
类库使得一系列的函数的调用更加合理,特别是当调用的这些函数不是能类的形式组织的时候,举一个例子,就象那些为简化在窗体中画图表的API函数而设计的类一样,这种类库在有些时候被叫做"Wrapper"。这些把API函数包括起来的类库通常可以简化操作,不过这样做并没有企图把API函数的一些基本特性给隐藏掉。Windows Graphics API函数有很多,但用户并不需要了解它底层的一些变化。用户在设计类的时候也是这样,必须考虑类库的用户对底层的了解程序。实际上,很多类库都是根据API函数来组织的,通常它们有两个趋势:使得API函数对高级用户更加方便,或者通过高度的概括,把这些底层的信息隐含起来,这意味着把Windows API函数的具体信息对用户封装。
但是这里又有一个隐含的关于开发类库的问题,被打成包的类导致了非常多的文字说明,把API简化得越多,需要的文字说明就越多。经常性的,几百个API函数被组织成一打或一百个类,每一个类具有几十个或几百个重叠的属性、方法和事件,整理或者浏览这个类将是工作量非常大的一件事。
设计和维护一个把各种API打包的类库,是一件工作量非常大的事情,设想现在要写一个类库来简化一个为Web服务的Html的网页的生成过程,这就需要先考虑一下自己是不是需要知道"Html";是不是需要把这些诸如"tags"或"angle brackets"的概念隐含掉;是不是向用户显示一些诸如字体等这些属性;是不是只要能处理Html就行了,还是需要处理XMl,能不能叫XHtml?等等。
假设一个基本类含有一个MustOverride方法叫做ParseHtml,然而当需要支持XMl时,就必须把Html支持替换掉,此时需要把方法ParseHtml清空,惟一的选择是建立一个ParseXMl方法,但不能把ParseHtml方法移除掉,因为当把该方法移除以后,就会导致Html业务的丧失,因为整个类是分布的,用户必须让ParseHtml和ParseXml方法同时存在,但这让内存和运行时间效率都减低了。
诸如这种问题在网络开发环境还是存在的,用户可能是过早设计了Html类库,也许一个基于接口的系统可以更好的解决这个问题。它让用户建立一系列的Html接口,当在确认XHtml或者XML是更好的基底时,就可以放弃或改善Html接口。
2.从基本类中得到重用的代码
使用继承的一个重要的原因就是为了代码的重用,然而这也是最危险的。正是因为代码的重用,即使是设计的最好的系统,有的时候也会出现一些设计者难以预料的改变。
一个经典的表示代码重用的高效率的例子就是一个数据管理库,设想现在有一个大型的应用程序,用来管理几个在内存中的清单,另一个是从顾客的数据中拷贝来的清单,该数据结构可以如下所示:
Class CustomerInfo Public PreviousCustomer As CustomerInfo Public NextCustomer As CustomerInfo Public ID As Integer Public FullName As String 'Adds a CustomerInfo to list Function Insertcustomer As CustomerInfo ... End Function 'Removes a CustomerInfo from list Function DeleteCustomer As CustomerInfo ... End Function 'Obtains next CustomerInfo in list Function GetNextCustmer As CustomerInfo ... End Function 'Obtains previous CustomerInfo Function GetPreCustomer As CustomerInfo ... End Function End Class 可能还有一张顾客的采购的东西的卡片清单,如下: Class ShoppingCartItem PreviousItem AS shoppingCartItem NextItem As ShoppingCartItem ProductCode As Integer Function GetNextItem As ShoppingCartItem ... End Function ... End Class
从这里,就可以看见类的结构和模式,都有相同之处--insertions(插入)、deletion(删除),以及traversal(浏览),只不过是对不同数据类型进行操作而已,显然,要维护这两段几乎具有相同函数的代码很没有必要,又一个显然的解决方案就是把对清单的处理抽象出来,做成一个它自己的类,然后,就可用这个类派生出不同数据类型的子类,如:
Class ListItem PreviousItem AS ListItem NextItem As ListItem Function GetNextItem As ListItem ... End Function ... End Class
这样的话,只需要对ListItem类调试一次,而且用户只需要把它编译一次以后,就不再需要管理关于清单管理的代码,用户只需要使用它就可以了:
Class CustomerInfo Inherits ListItem ID As Integer FullName As string End Class Class ShoppingCartItem Inherits ListItem ProductCode As Integer End Class
3.对不同的数据类型使用相同名称的类和方法
一个决定是否要使用继承办法就是是否有以下问题:
(1)是否需要对不同的数据类型进行相似的操作;
(2)需不需(想不想)访问程序源代码;
举一个非常具有代表性的例子,就是画图的软件包,假想它可以画圆、线和长方形。一个非常简单的而且效率很高的方法就是不需要使用继承,而用Select Case语句来实现,如下:
Sub Draw(Shape As DrawingShape,X As Integer,Y AS Integer,_ Size AS Integer) Select Case Shape.Type Case shpCircle 'Circle drawing code here End Case Case shpLine 'Line drawing code here End Case ... End Sub
但是这样处理的话将会出一些问题,将来如果需要添加画椭圆功能的话,那么就必须重新改写代码,也许最终用户不需要访问程序的源代码,但是可能画一个椭圆还需要一些参数,因为椭圆需要的参数是一个长半径和一个短半径。但是这些参数又和其他图形的参数无关,如果现在又要画一个折线(有多条线组成),则又需要加入一些其他的参数,而且这些参数又各其他的图形的参数无关。
继承就可以非常好地解决这些问题,一个设计得很好的类可以给用户留下一下很好的空间(MustInherit方法),那样的话,每一种图形都可以满足,但是一些类的属性(诸如XY坐标)可以作为基本类的属性,因为这个属性是每一种图形都需要的,如:
Class Shape Sub MustInherit Draw() X As Integer Y As Integer End Class
其他的图形都可以继承这个类,如要画一条线,代码如下:
Class Line Extends Shape() Length As Integer Sub Overrides Draw 'Implement Draw here End Sub End Class 长方形的类,又应该如下表示: Class Rectangle Extends Line() Width AS Integer Sub Overrides Draw() 'Implement Draw here End Sub End Class
它的继承子类(例如:长方形)能够在图象类的二进制的文件的基础上继承,而不是在基础类的代码的基础上继承。
4.基类的方法需要改变
Visual Basic(以及其他的提供继承的编程语言)使得用户有能力重载基本类的方法,只要在派生类中可以访问的基类的方法都可以被加载(除了那些NotInheritable)。假如用户感觉基本类的DisplayError方法需要给出一个错误号,而不只是错误的描述,则用户可以在派生类中改变这种方法的行为,则派生类会调用它本身的方法,而不是基类的方法。
5.通过改变一个基本类,就改变了所有的派生类
继承的一个强大的作用就是当改变一个基本类的属性时,就改变了所有的派生类的相应的结构,但是,这也是一个危险的行为--有可能改变了自己设计的基类后,别人由该基类而派生出来的派生类就会产生错误。
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索class
, 函数
, 方法
, function
, 用户
, 一个
as类
使用继承有什么好处、什么情况下使用继承、使用权房如何继承、宅基地使用权能否继承、不允许使用继承成员,以便于您获取更多的相关知识。