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

xiejingsha

xiejingsha

2016-02-19 18:26

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

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

  首先,我们知道多态是面向对象的三大特性之一。所谓多态,其思想就是,对于不同的具体类型,我们可以通过相同的抽象接口进行访问,而不必关系具体类型的实现细节。就像下达通知:所有员工明天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那么必须更改为子类的名字才行。

  其次如果被判断的对象有可能为空,使用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                   //无法编译通过;

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

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

(本文来源于图老师网站,更多请访问https://m.tulaoshi.com/bianchengyuyan/)
展开更多 50%)
分享

猜你喜欢

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

编程语言 网络编程
Delphi中避免使用ClassName判断对象的类型

Delphi中的布尔类型

编程语言 网络编程
Delphi中的布尔类型

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

Delphi中对象解除技巧

编程语言 网络编程
Delphi中对象解除技巧

JavaScript使用prototype定义对象类型

Web开发
JavaScript使用prototype定义对象类型

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

javascript中获取选中对象的类型

Web开发
javascript中获取选中对象的类型

Delphi中使用纯正的面向对象方法

编程语言 网络编程
Delphi中使用纯正的面向对象方法

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

Win10企业版、专业版和家庭版的区别

Win10企业版、专业版和家庭版的区别

Delphi编写数据库程序要点(一)

Delphi编写数据库程序要点(一)
下拉加载更多内容 ↓