Henry的VB.NET之旅(七)—脆弱的基类

原创 2003年11月14日 08:40:00

      Henry的VB.NET之旅(七)—脆弱的基类<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

                             韩睿

 

“既然说是脆弱,当然是指它象蛋壳一样不堪一击喽。这个问题其实很好理解。程序总是由人来设计与编写的,所以工作开始时考虑不到某些问题当然也是很正常的事。所以可能在工作进行了一段时间后发现基类需要变更。你想,如果我在基类中更改了成员的数据类型,以及那些允许重写的那些方法和属性,那派生类及其子类还能正常工作吗?尤其是当一个团队中的多个开发人员一起来创作基类和派生类时,就更是要命了。很多情况下,大家可能已经把基类和一些派生类编译成二进制形式进行提交了。更改基类,重新编译再分布,会牵一发而动全身,导致项目的崩溃。所以我们把这叫做‘脆弱的基类’。也就是说,它是整个工程中最薄弱最致命的环节。”大李眉头一直紧锁着,想必是回想起了自己受打击的经历。

“这么严重呀,现在的软件工程设计方法会不会对这个有很好的解决方案?”我努力想缓解一下大李的严肃神情。

“如果对项目的前期设计考虑尽可能周详,在工程实施中对项目的代码控制与相关性分析做得踏实,会起到很好的效果。但是不管一个人如何努力,有时还是无法避免对基类进行不可预见的更改。我们摸索过很久,有了一些处理的手段。”

“真是成事在人呀,我们现在有什么解决之道?”我也一下子振奋起来了。

“呵呵,并不是什么完美解决方案。只能在某种程度上减轻危害。我们常用的一个方法,最直接的思想就是,把有可能发生的更改全都放在派生类中进行,不在基类中做。”

“这具体是什么意思呀,我还是不太明白。”我不好意思地挠挠头。

大李微笑着点点头,看来是知道我不会明白的了。“我们在基类中使用的是抽象类,它内含的方法与属性只有定义,没有进行实现,而把实现部分都放在派生类中做。这样一来,抽象类自身是无法被实例化的。但是它的好处不言而喻,就是有可能发生的实现上的更改都会只涉及到它的派生类了。VB.NET中就提供了这样的手段。”

说着,大李就打开VS.NET集成编译环境,顺手写了一小段代码:

Public MustInherit Class CBaseHenry

??? Public MustOverride Sub subX(ByVal x As Integer)

??? Public MustOverride Function fcnY(ByVal y As Integer) As Long

End Class

Public Class CDerivedHenry

??? Inherits CBaseHenry

??? Public Overrides Sub subX(ByVal x As Integer)

?????? ?'写入实现的代码

??? End Sub

??? Public Overrides Function fcnY(ByVal y As Integer) As Long

??????? '写入实现的代码

??? End Function

End Class

?

“这里要注意两个问题,一个是关键字,我们用MustInherit来修饰类名,使类成为抽象类,在它的成员中,把方法和属性前加入MustOverride修饰符表示它们必须在派生类中加以实现。第二个要注意的是,派生类必须对所有用MustOverride标识的基类方法和属性都进行实现,只重写了subX,不写fcnY编译器会报错的。”

“这的确可以解决一部分问题,但好象只能解决在基类中进行实现的代码有更改的问题,对于数据类型的更改好象没有什么效果。”我看了好一会,发出了这样的疑问。

“所以我刚才说,是在某种程度上进行解决嘛。”大李也不由笑了起来,“不过你提的这个问题,倒不是太麻烦,我们可以在派生类中用Shadows来解决呀!(详见本报上一期《重载与隐藏》)”

这倒是个不错的主意,我心中暗暗评价了一番。突然我又想到一个问题:“如果基类要做功能扩展,怎么办呀?”

“如果是要做扩展,最安全的方法是添加新成员,而不是对基类的大肆修改。一般是往派生类添加设计时缺失的新成员。最好不要使用Overloads关键字来命名与基类相同的成员,那样往往会带给你意想不到的问题。最好重新定义新成员,命名上也要尽量与基类已有的成员名区分开来。其实,也可以往抽象类基类中添加新成员的定义,但这样一来,需要为基类制定版本,虽然不会对应用程序造成毁灭性的危害,但是应该要能够完全地控制与管理自己的代码。我们一般是不希望扩展基类的。”

我已经大意上领会了大李的一片苦心:“您的意思,是不是指基类的脆弱问题实际上是客观存在的,我们所做的就是要最大程度的减小这个问题带来的危害?”

大李眼中闪过一丝赞许的笑意,颌首道:“没错,对于一个应用程序的设计者来讲,想使用面向对象方法来开发,必须要在设计的时候精心策划类的层次结构。一般来说,是有这样几个准则需要把握的:

第一,遵循先通用,再专用的原则。先设计好层次结构中每一级别的类中的通用部分,也就是提供给派生类继承的成员和标识为Public的成员;

第二,在定义数据类型和存储区时要有预留量,以避免以后更改困难。例如,即使当前数据可能仅需要Integer类型就够了,在设计时我们使用 Long 类型的变量。当然,最好能物尽其用,也不要盲目放大;

第三,在一个项目中,必须统一管理与分配团队中使用的所有的命名,以减少命名冲突,这一点其实事关重大;

第四,要使用提供可行的最低访问权限的访问修饰符声明类成员。内部类成员应声明为 Private;仅在类内与派生类才需要的成员应标记为ProtectedFriend 数据成员可以从类的外部访问,但仅限于该模块是定义该类的项目的一个组成部分;使用Public标识的成员,只能是实例化时真正需要的内容,而且经常用在类层次结构的底部。”

“也就是说,一个规范的操作,标准的命名体系可以决定基类的强壮与否?”我不禁感触了一声。

“不对,应该这样说,可以决定的是给脆弱的基类穿上多厚的防护衣。因为基类始终都是脆弱的。”大李更正道。

我连声赞同:“对,对。我现在是真正明白为什么总有人提编程规范的事情,我一直认为是增强代码的可读性,没想到,对程序自身还有这么大的帮助。”

“当然,其实你认真想一下,Overrides关键字的作用,不管要不要注明,编译器都可以很方便地判断方法或属性是否在基类中,签名是否匹配,但是VB.NET要求我们必须标注,就是强制开发人员注明重载基类方法或属性的意图,使开发过程更合理与有效。此外,还有更重要的就是,我们要在工程实践中不断地学习与磨练,了解更多的知识,获得更多的经验,这样才会成长为一名合格的程序设计师。就拿继承来说吧,在.NET中其实支持三种继承方式:实现继承、接口继承、可视继承。我们其实只用了第一种继承方式,你看,要学的东西是不是很多?”大李友好地拍了拍我的肩膀。

(未完待续)

---------------------------------------------------------------

声明:本文版权与解释权归韩睿所有,如需转载,请保留完整的内容及此声明。

QQ: 18349592

E-Mail: henry7685@hotmail.com

请访问本人专栏:http://www.csdn.net/develop/author/netauthor/Latitude/

脆弱的基类问题

英语原文:http://www.cocoawithlove.com/2010/03/dynamic-ivars-solving-fragile-base.html 中文原文:http://blog....
  • hudashi
  • hudashi
  • 2016年06月27日 21:01
  • 459

VB.NET之旅(七)—脆弱的基类

“既然说是脆弱,当然是指它象蛋壳一样不堪一击喽。这个问题其实很好理解。程序总是由人来设计与编写的,所以工作开始时考虑不到某些问题当然也是很正常的事。所以可能在工作进行了一段时间后发现基类需要变更。你想...
  • hao8986
  • hao8986
  • 2012年01月05日 14:47
  • 415

关于VB.NET基类继承、重载、隐藏的总结归纳

文章主要介绍了VB.NET基类的继承,重写,重载,隐藏,VB.NET类成员访问的修饰符Friend,private ,protected,protected friend,public 。 ...
  • qq2644375193
  • qq2644375193
  • 2012年11月28日 13:34
  • 543

Henry的VB.NET之旅(九)—接口继承

?????? Henry的VB.NET之旅(九)—接口继承?????????????????????????????????????? 韩睿?大李拍了拍我的肩膀说:“你真有想象力,不过的确,有很多文献...
  • Latitude
  • Latitude
  • 2003年12月11日 11:42
  • 4108

Henry的VB.NET之旅(五)—类的继承

????????????? Henry的VB.NET之旅(五)—类的继承??????????????????????????????????????? 韩睿?“类的继承?”大李点点头,“以前很多人批评...
  • Latitude
  • Latitude
  • 2003年11月14日 08:40
  • 3216

Henry的VB.NET之旅(八)—接口

?????? Henry的VB.NET之旅(八)—接口??????????????????????????????????? 韩睿?“还有两种继承方法?”我是真正被VB.NET的强大功能所折服了。求知...
  • Latitude
  • Latitude
  • 2003年12月11日 11:41
  • 3815

韩睿(Henry Han)的VB.NET之旅

 要抽空学学才行。 《韩睿(Henry Han)的VB.NET之旅》http://blog.csdn.net/latitude/article/category/15494...
  • zslefour
  • zslefour
  • 2014年03月12日 20:57
  • 845

Henry的VB.NET之旅(十二)—事件驱动

       Henry的VB.NET之旅(十二)—事件驱动                                    韩睿 “可视继承原来这么方便!”我心中默默地感叹一声。一会儿之后,我...
  • Latitude
  • Latitude
  • 2004年02月05日 00:48
  • 4637

Henry的VB.NET之旅(十一)—可视继承

???? Henry的VB.NET之旅(十一)—可视继承???????????????????????????????? 韩睿?闭关修练了一晚上VB.NET的继承程序的我,早上进入公司时自信满满。白经...
  • Latitude
  • Latitude
  • 2004年02月05日 00:47
  • 3635

Henry的VB.NET之旅(三)—共享成员

?????????????????????????????????? Henry的VB.NET之旅(三)—共享成员????????????????????????? 韩睿?我开始佩服起大李来了,同时对...
  • Latitude
  • Latitude
  • 2003年11月14日 08:34
  • 2533
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Henry的VB.NET之旅(七)—脆弱的基类
举报原因:
原因补充:

(最多只允许输入30个字)