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

Google
深入Delphi编程
作者:Siny 文章来源:中国教师站cn-teacher 点击数: 更新时间:2007-4-22 16:01:41
法(Virtual Method)。而在TNewClass中,One方法后面多了一个Override关键字,表示该方法进行了重载(Override)。重载技术能够实现许多特殊的功能。
  让我们来仔细分析它们的实现部分。在TMyclass.One方法的实现部分,调用ShowMessage过程弹出一个对话框,说明该方法已被调用;这里没有任何特别的地方。在TNewClass.One方法中,出现了一条以前从未出现过的语句:
  
  Inherited;
  
  这个词的中文意思是“继承”。我们暂时不要去涉及到太过复杂的OOP概念,只要知道这条语句的功能就是了。它的功能是调用基类中相当的虚拟方法中的代码。例如,你如果使用以下代码:
  
  var
  AObject: TNewClass;
  begin
  AObject := TNewClass.create;
  AObject.One;
  AObject.free;
  end;
  
  那么程序将弹出两次对话框,第一次是调用TMyclass类中的One方法,第二次才是TNewClass.One方法中的代码。
  重载技术使得我们不但可以在派生类中添加基类没有的数据和方法,而且可以非常方便地继承基类中原有方法的代码,只需要简单地加入Inherited就可以了。如果你不加入Inherited语句,那么基类的相应方法将被新的方法覆盖掉。但是必须注意,重载只有在基类的方法被标志为Virtual时才能进行,而且重载的方法必须具有和虚拟方法完全相同的参数类型。
  虚拟方法还有一种特例,即抽象方法:
  
  procedure One;override;abstract;
  
  在One方法后面,不但有override关键字,还多了一个abstract关键字(意为抽象)。这种方法称为抽象方法(在C++中称为纯虚拟函数)。含有抽象方法的类称为抽象类。抽象方法的独特之处在于,它只有声明,而根本没有实现部分,如果你企图调用一个对象的抽象方法,你将得到一个异常。只有当这个类的派生类重载并实现了该方法之后,它才能够被调用。(在C++中,甚至根本就不能建立一个抽象类的实例。)
  既然如此,那么这种抽象方法又有什么用呢?这个问题我们将在接下来的“多态”部分进行讨论。
  
  1.3 多态
  
  多态相对来说比较复杂一点。不过不要担心,它的内容比较少,而且如果以前的知识掌握得比较稳固的话,多态的概念是水到渠成的。
  先来讨论一下类型的兼容性问题。下面是一个例子:
  
  type
  TAnimal = Class
  Procedure Voice;virtual;
  ...
  end;
  
  TDog = Class(TAnimal)
  Procedure Voice;Override;
  ...
  end;
  
  implementation
  
  Procedure TAnimal.Voice;virtual;
  Begin
  PlaySound('Anim.wav',0,snd_Async);
  End;
  
  Procedure TDog.Voice;virtual;
  Begin
  PlaySound('Dog.wav',0,snd_Async);
  End;
  
  TDog类继承了TAnimal类,并重载了其中的Voice方法。PlaySound是一个WIN API函数,可以播放指定的wav文件。(这个函数的定义在MMSystem.pas文件中可以找到。)
  先看这段代码:
  
  var
  MyAnimal1, MyAnimal2: TAnimal;
  Begin
  MyAnimal1 := TAnimal.Create;
  MyAnimal2 := TDog.Create;
  ...
  
  在实现部分的第一行中,建立了一个TAnimal类型的对象,并将其赋予TAnimal类型的变量MyAnimal1。这是很正常的事。但在第二行中,建立了一个TDog类型的对象,并将其赋予了TAnimal类型的变量MyAnimal2。这看上去令人吃惊,但这些代码是完全合法的。
  众所周知,Pascal以及Object Pascal是一种类型定义严格的语言,你不能将某个类型的值赋予不同类型的变量,例如将一个整型值赋予布尔型变量,将会导致出错。但是,这个规则在涉及到OOP领域时,出现了一个重要的例外,那就是:可以将一个子类的值赋予一个父类类型的变量。但倒过来却是不行的,一个父类的值决不能赋予一个子类类型的变量。
  如果将这个原则放到现实世界中,那就很容易理解了:“狗”继承自“动物”,因为狗也是一种动物。所以可以将一个“狗”类型的值赋予“动物”类型的变量,因为“狗”具有“动物”的一切特征。但反过来,“动物”不具有“狗”的所有特征,因此反向赋值是不行的。
  那么,这种兼容规则在编程中究竟有什么用处呢?
  请注意下面这段代码:
  
  var
  MyAnimal1, MyAnimal2: TAnimal;
  Begin
  MyAnimal1 := TAnimal.Create;
  MyAnimal2 := TDog.Create;
  MyAnimal1.Sound;
  MyAnimal2.Sound;
  ...
  
  MyAnimal1和MyAnimal2都是TAnimal的变量,而且都调用了Sound方法。但是,执行的结果是完全不同的:前者执行的是TAnimal.Voice的代码,而后者执行的是TDog.Voice的代码!其原因很简单,因为MyAnimal1被赋予了TAnimal类型的对象,而MyAnimal2被赋予了TDog类型的对象。也就是说,一个TAnimal类型的变量,当它调用Sound方法时,所执行的代码是不确定的:可能执行TAnimal.Voice的代码,也可能执行的是TDog.Voice的代码,取决于它当时引用的是一个什么样的对象。
  再看:
  
  MyAnimal1 := TAnimal.Create;
  MyAnimal1.Sound;
  MyAnimal1.free;
  MyAnimal1 := TDog.Create;
  MyAnimal1.Sound;
  ...
  
  同一个变量MyAnimal1,在第一次调用Sound方法时,执行的是TAnimal.Voice的代码,在第二次时执行的是TDog.Voice的代码。MyAnimal1.Sound这行代码不需要变化,程序可以根据不同的情况赋予该变量不同的对象,从而使它执行不同的代码。这就是多态的定义。
  这个非常重要的特点大大地增加了代码的可复用性。如前所述,只需要简单地写下一行代码,就可以让程序执行不同的功能,因为这个虚拟方法同TAnimal的任何派生类都是兼容的,甚至连那些还没有编写出来的类也是一样。而程序员并不需要了解这些派生类的细节。利用多态性写出来代码,还具有简洁和维护性好的特点。
  现在我们可以回到本文的1.2节结尾处的问题了。抽象方法本身不能够做任何事情,必须在子类中被重载并实现,才能够完成有意义的工作。但抽象方法的存在,相当于为父类留下了一个接口,当程序将一个子类的对象赋予父类的变量时,父类的变量就可以调用这个方法,当然此时它运行的是相应的子类中重载该方法的代码。如果没有这个抽象方法,父类的变量就不能调用它,因为它不能调用一个只在子类中存在、而在父类中不存在的方法!
  
  关于OOP的介绍就到此这止。在以上这些篇幅里,介绍的只是OOP最基本的一些概念,让读者对OOP有一定的系统认识,也为

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

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

阅读排行

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

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

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