什么时候使用继承

继承是一个非常有用的概念,但是却很容易被用得不合适,通常用接口来实现可能会更好,本文的目的就是使用户懂得怎样更好的使用类的继承。
当遇到如下情况时,继承将是一个好的选择:
(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类
使用继承有什么好处、什么情况下使用继承、使用权房如何继承、宅基地使用权能否继承、不允许使用继承成员,以便于您获取更多的相关知识。

时间: 2024-11-02 02:27:07

什么时候使用继承的相关文章

android java 继承父类里的子类问题!!!!!!!

问题描述 android java 继承父类里的子类问题!!!!!!! 请问各位,java可以继承父类的方法和全部属性,那父类里的子类可以继承使用么? android 可以继承父类的Handler.广播么??

pb9继承方法-pb9如何在数据窗口继承方法

问题描述 pb9如何在数据窗口继承方法 如何解决,望大神赐教!!! 解决方案 [PB]从数据窗口获得数据的方法总结pb从数据窗口获得数据的方法总结pb从数据窗口获得数据的方法总结

maven pom聚合与继承

说到聚合与继承我们都很熟悉,maven同样也具备这样的设计原则,下面我们来看一下Maven的pom如何进行聚合与继承的配置实现. 一.为什么要聚合? 随着技术的飞速发展和各类用户对软件的要求越来越高,软件本身也变得越来越复杂,然后软件设计人员开始采用各种方式进行开发,于是就有了我们的分层架构.分模块开发,来提高代码的清晰和重用.针对于这一特性,maven也给予了相应的配置. 情景分析一: 我们在开发过程中,创建了2个以上的模块,每个模块都是一个独立的maven project,在开始的时候我们可

子类继承HibernateDaoSupport后如何注入SessionFactory

子类继承HibernateDaoSupport后,由于HibernateDaoSupport,setSessionFactory是使用final修飾的,無法重寫,沒有辦法使用註解的方式注入sessionFactroy public final void setSessionFactory(SessionFactory sessionFactory) {         if (this.hibernateTemplate == null || sessionFactory != this.hib

JAVA 【引用类型】和【对象类型】在【继承】中的异同

介绍     JAVA [引用类型]和[对象类型]在[继承]中的异同,这个问题自己整理过N次,也被人当菜鸟问过N次.所以,在此简单整理一下,以供大家分享. 在继承关系中,一般成员变量是根据引用类型 在继承关系中,静态成员变量是根据引用类型 在继承关系中,一般方法是根据对象类型 在继承关系中,静态方法是根据引用类型 注意     静态成员变量,静态方法是基于类的,本文为了测试观察,所以,会用对象去引用静态成员变量和静态方法.      Super Class: package shuai.stud

如何用语句去实现多层继承

问题描述 如何用语句去实现多层继承 Person类,有Student类和Employee类继承Person, 而Employee类又被教员类Teacher类和职员类Staff类继承. 每个人都有姓名.地址.电话号码和电子邮件地址. 学生有年级状态(大一到大四). 雇员有办公室(office).工资(salary)和受聘日期(dateOfEmployee). 教员有办公时间(wordTime)和级别(level). 职员有职位(job). 覆盖每个类的toString()方法,显示相应的类名和人名

c++-类继承方面的问题,求教

问题描述 类继承方面的问题,求教 class A{ public : A* a; A(){a = this;}};class B : public A{public: B(){};}; void main(){ B* b = new B;; cout<< b << "" "" << b->a <<endl; getchar();} 为什么两次输出的结果是一样的,都是指向,A类对象在创建的时候,b还不存在,this

java继承

* 继承(extends) * java是一种树形结构(联结类的层次模型),单继承(父类),多实现(接口+内部类) * 子类和父类之间是is-a关系 * 在子类中使用super关键字,访问父类的成员,super必须出现在子类.本类中方法中this调用本类的成员(属性和方法,区别于局部变量),在构造方法中调用(替代)其他构造方法 * 继承规则:①不能继承private成员 *                 ②子类和父类不在同包时,不能继承default默认修饰符成员 *            

C#继承

继承(C# 编程指南) 类可以从其他类中继承.这是通过以下方式实现的:在声明类时,在类名称后放置一个冒 号,然后在冒号后指定要从中继承的类(即基类).例如: public class A { public A() { } } public class B : A { public B() { } } 新类(即派生类)将获取基类的所有非私有数据和行为以及新类为自己定义的所有其他数 据或行为.因此,新类具有两个有效类型:新类的类型和它继承的类的类型. 在上面的示例中,类 B 既是有效的 B,又是有效

java网络传递对象时该对象继承父类的属性在网络接收端接收该属性值总是null,why?

问题描述 java网络传递对象时该对象继承父类的属性在网络接收端接收该属性值总是null,why? //=========================== 情形一: ===============================//在网络上传递User1类对象时info属性值在网络的另一端能够接收到! public class User1 implements Serializable { public String info = null; public String userName =