Delphi中避免使用ClassName判断对象的类型

2016-02-19 18:26 32 1 收藏

下面是个简单易学的Delphi中避免使用ClassName判断对象的类型教程,图老师小编详细图解介绍包你轻松学会,喜欢的朋友赶紧get起来吧!

【 tulaoshi.com - 编程语言 】

 

  在公司原有系统的代码中,我看到了很多判别对象的ClassName属性进行分别处理的代码。而且似乎已经是处理类似问题的标准方法。但是其中可能会隐含一些问题。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  首先,我们知道多态是面向对象的三大特性之一。所谓多态,其思想就是,对于不同的具体类型,我们可以通过相同的抽象接口进行访问,而不必关系具体类型的实现细节。就像下达通知:所有员工明天9点在人民广场集合。并不需要具体通知每个住在不同位置的人应该几点出发,走什么路线,因为这是具体的人的责任,而非通知下达者的责任。所以,在写到需要判断ClassName进行分别处理的时候,首先应该想到的处理方式是在父类中增加接口,通过子类override完成。如下面改变把图形大小的代码:
      for i := 0 to 图形列表.Count - 1 do
      begin
        图形 := 图形列表[i];
        if 图形.ClassName = '长方形' then
        begin
          长方形(图形).长 := 长方形(图形).长 * 2;
          长方形(图形).宽 := 长方形(图形).宽 * 2;
        end
        else if 图形.ClassName = '圆形' then
        begin
          圆形(图形).半径 := 长方形(图形).半径 * 2;
        end  
      end;
     
  就可以在父类“图形”中增加“ChangeSize”方法,代码如下
      图形 = class
        ……
        procedure ChangeSize(rate: Integer); virtual;
      end;
     
      长方形 = class
        ……
        procedure ChangeSize(rate: Integer); override;
      end;
     
      圆形 = class
        ……
        procedure ChangeSize(rate: Integer); override;
      end;
  在具体的图形类中实现大小改变的代码:
      procedure 长方形.ChangeSize(rate: Integer);
      begin
        长 := 长 * rate;
        宽 := 宽 * rate;
      end;
     
      procedure 圆形.ChangeSize(rate: Integer);
      begin
        半径 := 半径 * rate;
      end;
  这样修改后,上面的代码就可以这样调用了:
      for i := 0 to 图形列表.Count - 1 do
      begin
        图形 := 图形列表[i];
        图形.ChangeSize(2);
      end;
  这样代码的意图清晰了很多。

  当然,在很多时候,出现判断ClassName的情况下并不能采用上边的解决方法。比如遍历Form的Cotrols并对不同的控件进行分别初试化。我们不可能去TControl中增加初始化方法,只有采用判别具体子类类型。那么这时我推荐采用is运算符而非直接比较ClassName。
  is的用法,语句 aObject is TForm 在不同的aObject的类型情况下结果如下:
      aObject是TObject,结果为假;
      aObject是TForm,结果为真;
      aObject是TForm1,结果为真;
      aObject是TEdit,结果为假;
      aObject是nil,结果为假;
  从上面示例可以看到采用is的一个优点,is可以判断是否子类的情况,比如我们在初始化控件的时候根据是TImage还是TEdit作不同的初始化,通过is判断处理。将来也许会采用TCoolEdit来美化界面,那么这段代码不需要更改,因为一个TCoolEdit是一个TEdit;而如果采用ClassName那么必须更改为子类的名字才行。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  其次如果被判断的对象有可能为空,使用ClassName判断必须先判断对象是否赋值,否则就会出现内存访问错误。判断代表必须写为:if Assigned(aObject) and aObject.ClassName = 'TClass1';而采用is只需要写为if aObject is TClass1。
  最后一个不采用ClassName作为判定的原因是,ClassName只是用来描述一个类的属性,字符串比较不能在编译期获得检查,如果存在拼写错误,或是大小写问题代码都会出现逻辑错误,而这种错误只有在运行期运行到这一语句的时候才会被发现。
      if aControl.ClassName = 'TEidt' then       //只有在你注意到Edit没有初试化时才会来检查这段代码;
      if aControl is TEidt then                   //无法编译通过;

  综合上面所述,在需要判定一个对象的具体类型时,首先应该考虑通过多态处理避免这种分别特殊处理的语句,实在不能避免的情况下应该采用is运算符判断,而非ClassName。
  在一种很特殊的情况下,is可能不能得到想要的结果,比如需要分别处理TEdit和TCoolEdit的情况,用is的话CoolEdit也会判断为TEdit,这时可以采用ClassType方法,也要胜过没有类型检测的字符串比较:
      aCoolEdit is TEdit               //True;
      aCoolEdit.ClassType = TEdit      //False;
      aCoolEdit.ClassType = TCoolEdit  //True;

来源:http://www.tulaoshi.com/n/20160219/1617656.html

延伸阅读
1. 首先String不属于8种基本数据类型,String是一个对象。 因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。 2. new String()和new String("")都是申明一个新的空字符串,是空串不是null; 3. String str="kvill"; String str=new String ("kvill");的区别: 在这里,我们不谈...
Delphi的编程语言是以Pascal为基础的。Pascal语言具有可读性好、编写容易的特点,这使得它很适合作为基础的开发语言。同时,使用编译器创建的应用程序只生成单个可执行文件(.EXE),正是这种结合,使得Pascal成为Delphi这种先进开发环境的编程语言。 本章中,我们将讨论Object Pascal的主要特点,并讲解如何在事件处理过程和其他应用程...
标签: Delphi
  资源是存放在扩展名.RES的文件里的二进制数据结构,在DELPHI中资源文件可以使用图象编辑器来制作(IMAGEEDITOR),或者使用其他的工具。如:BORLAND公司提供的RADPACKFORDELPHI中的RESOURCEWORKSHOP来创建。资源文件中通常存放的是应用程序可以随时存取的一些对象,包括:ICON、CURSOR、BITMAP、FONT等近十种。大部分的资源在通常的...
作为一个ASP爱好者,笔者经常在ASP页面中使用ADO对象操作ODBC数据库,觉得用ASP创建WEB应用系统确定挺方便的.虽然在编程生涯中,笔者更喜欢Borland系列产品,对微软产品有点排斥,对ASP却是例外.某天,灵机一动,ADO对象是一个标准OLE对象,如果在DELPHI应用程序中能利用ADO操作数据库,应该挺不错.尤其在用DELPHI做网络数据库应用程序...
具体的DLL封装对象请看刘艺的《Delphi中的DLL封装和调用对象技术》及配书源码。 本人在使用DELPHI编制DLL过程中碰到了些奇怪的问题,现在将其列出来,仅供参考: 1、DELPHI生成的DLL工程中写到:ShareMem must be the first unit in your library's USES clause AND your project's。这里提到的是DLL工程和使用该DLL的工程都需...

经验教程

867

收藏

44
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部