您现在的位置: 中国教师站 >> 教师关注 >> 电脑技术 >> 编程技术 >> Delphi >> 正文

Google
深入Delphi编程
作者:Siny 文章来源:中国教师站cn-teacher 点击数: 更新时间:2007-4-22 16:01:41
明类的派生类中被访问,然而仍然不能被这两种情况以外的其他代码所访问。现在我们终于可以理解了,这个特殊的属性实际上提供了极大的方便:它使得类的成员被封装,避免了混乱,同时又能够让派生类方便地使用它们。
  (如果你是一个细心的人,你可能发现上面的话中间有一个小小的仳漏。当你真的在GetTextNew方法中访问了基类的Private成员的话,你可能会惊奇地发现程序也能够编译通过而且正常运行!其实,这个问题和OOP本身没有关系。上面我已经说过,在Delphi中,Private成员在声明类所在的单元文件中的任何地方都能被访问,因此如果TNewDate类和TDate类在同一个.pas文件中时,这种情况就不足为怪了。)
  怎么样,是不是觉得非常奇妙?通过这种继承的机制,类不再仅仅是数据和方法的封装,它提供了开放性。你可以方便地继承一个功能强大的类,然后添加进自己需要的特性,同时,你又不需要对基类进行任何的修改。相反,原作者对基类的任何改动,都可以在你的新类中立即反映出来。这非常符合代码的重用要求。
  这种继承机制也非常符合现实世界中的情形。可以设想,一般意义上的“动物”是一个类,具有自己的一些特征(成员);而“狗”是“动物”的派生类,它具有动物的所有特征,同时还具有自己独有的特征(四条腿,汪汪叫,等等)。而“狗”这个类可以继续派生下去,例如“黑狗”“白狗”,它们除了保留狗的全部特征之外,还具有自己的特征(黑颜色,白颜色,等等)。而具体到一只活生生的狗,可以认为它就是“黑狗”或“白狗”(或其他什么狗)的一个实例(对象)。
  OOP这种对现实世界的模拟不仅极大地简化了代码的维护,而且使得整个编程思想产生了革命性的变化,较之模块化编程有了飞跃的进步。
  如果你曾经仔细阅读过VCL的资料甚至它的源代码,你就可以发现,整个VCL都是建立在这种强大的封装-继承的机制之上的。你可以看到一张详细的VCL层次结构图,就象是一个庞大的家谱,各种VCL构件通过层层继承而产生。例如,一个简简单单的TForm类,就是许多次继承之后的产物:
  TObject - TPersistent - TConponent - TControl - TWinControl - TScrollingWinControl - TCustomForm - TForm
  不但Delphi的VCL,Visual C++中的著名的MFC(Microsoft Foundation Class,微软基本类库),以及以前Borland C++中风光一时的OWL(Object Window Library,对象窗口类库),都是建立在这种机制之上。所不同的是,对于前两种语言,你要花上好几个月的功夫去基本掌握那些繁复无比的类,才能写出比较有实用价值的程序,而在Delphi中,大部分的工作Delphi都已经自动帮你完成了。例如,每次你向程序中加入一个窗体时,Delphi就自动为你从TForm派生一个新类(默认为TForm1),并且为这个新类创造一个实例。你对这个窗体的改动(添加构件和代码之类),无非是为这个派生类加入一些新的特性而已;你再也用不着自己去处理最大化、最小化、改变大小这一类的情况,因为这些代码都在基类中被实现,而被派生类所继承了。这就是Delphi的伟大之处。当然,Delphi的VCL也绝不比MFC或OWL逊色(事实上它是由后者演变而来)。
  (可能有人会问起VB的情况。VB不支持继承,因此并没有什么复杂的类库,它自己的控件也少得可怜,主要是使用ActiveX控件。)。
  也许你已经若有所悟,为你的发现而心痒难骚了吧。但是,我们要讨论的东西当然不会仅仅这么简单。
  在1.1部分(“数据封装”),我们讲到了“Create方法是每一个Class都具有隐含的方法”。其实,这种说法是不准确的。事实是,在Delphi中,所有的类都默认继承自一个最基础的类TOject,甚至在你并未指定继承的类名也是如此。Create方法是TObject类具有的方法,因此理所当然,所有的类都自动获得了Create方法,不管你是否实现过它。想想看就知道了:如果没有Create方法的话,怎样建立一个对象呢?
  你可能注意到了Create方法是一个特殊的方法。不错,Create方法的确非常特殊,甚至于它的“头衔”不再是function或procedure,而是Constructor(构造器)。你可以在VCL的源码中见到这样一些例子:
  
  Constructor Create;
  
  构造器不仅是一个Delphi关键字,而且是一个OOP方法学的名词。与之相对应的,还有Destructor(毁坏器)。前者负责完成创建一个对象的工作,为它分配内存,后者负责释放这个对象,回收它的内存。要注意的一点是,Constructor的名字一般是Create,但Destructor的名字却不是Free,而是Destroy。例如:
  
  Destructor Destroy;
  
  那么,在以前的代码,为什么又使用Free来释放对象呢?二者的区别是,Destroy会直接释放对象,而Free会事实检查该对象是否存在,如果对象存在,或者对象不为nil,它才会调用Destroy。因此,程序中应该尽量使用free来释放对象,这样更加安全一些。(但要注意,free也不会自动将对象置为nil,所以在调用free之后,最好是再手动将对象置为nil。)
  象对待一般的函数或过程那样,也可以向构造器传递参数:
  
  type
  TDate = class
  private
  Mouth,day,Year:Integer;
  Public
  function LeapYear:Boolean;
  function GetText:String;
  Constructor Create(m,d,y:Integer);
  end;
  
  procedure TDate.Create(m,d,y):Integer;
  begin
  Mouth := m;
  Day := d;
  Year := y;
  end;
  
  调用它:
  
  ADay: TDate;
  begin
  ADay := TDate.create(1,1,2000);
  if ADay.LeapYear then
  ShowMessage('闰年:' + Inttostr(ADay.year));
  ADay.free;
  end;
  
  这样,在Create方法里就完成了对数据的初始化,而无须再调用SetValue方法了。
  
  接下来,我们将要涉及到另一个重要的、也是很有趣的问题:方法的虚拟与重载。
  可能你已经有点晕了吧……还是先看一个新的例子:
  
  type
  TMyClass = class
  procedure One;virtual;
  end;
  
  type
  TNewClass = class(TMyClass)
  procedure One;override;
  end;
  
  procedure TMyclass.One;virtual;
  begin
  ShowMessage('调用了TMyclass的方法!');
  end;
  
  procedure TNewClass.One; override;
  begin
  Inherited;
  ShowMessage('调用了TNewClass的方法!');
  end;
  
  可以看到,从TMyClass派生了一个新类TNewClass。这两个类都声明了一个名字相同的方法One。所不同的是,在TMyClass中,One方法后面多了一个Virtual关键字,表示这个方法是一个虚拟方

上一页  [1] [2] [3] [4] [5] [6] [7] [8] 下一页

相关专题:
 
 网友评论:(评论内容只代表网友观点,与本站立场无关!)
GOOGLE广告

阅读排行

| 设为首页 | 加入收藏 | 联系站长 | 友情链接 | 版权申明 |
中国教师站

中国教师站 版权所有 Copyright © 2006-2020 All Rights Reserved 站长:Sina & Siny
[备用域名:www.JXZYW.Com] 有事请留言有事请留言
【实力成就精品 诚信呵护品牌】

信息产业部备案
苏ICP备06018635号