求AS的用法,如题 ( 积分: 50 )

  • 主题发起人 主题发起人 dywapple
  • 开始时间 开始时间
D

dywapple

Unregistered / Unconfirmed
GUEST, unregistred user!
假设Object为某控件,
TEdit(Object)
(Object As TEdit)
这两种方式的差别是什么?
 
都是类型转化的语法,
基本上没有什么差别
 
有差别:
TEdit(Object)方式:要求Object与TEdit有继承关系.例如:Object为TEdit的子类.如果TEdit(Object)....,则表示将得到object的父类属性,而该属性并未在object中得到继承。
(Object As TEdit)方式:指的是某一个对象object,并且把他作为TEdit类作为处理。
 
未必需要继承的,接口也是可以强制类型转化的。
比如
F:TForm

TButton(F).Caption:='OK'
保证不会有问题,但是TButton不是从TForm继承的。
 
as 操作符强制把一个对象变量的类型转换为另一个类的类型,
或把一个接口变量变换为另一个接口的类型;
想要转换的对象所声明的类必须是目标类的后代或祖先,否则不兼容。
有时结合is 操作符来判断对象的类型~
 
duxing说得很对,不过有些东西有时候可以灵活使用的,
所以,我上面的代码语法上,逻辑上都说不过去,但是,可以编译通过,也能达到预期的效果,而且也不会有问题,
在某些场合用用也是可以体现一个设计的思路。
 
procedure TForm1.Button1Click(Sender: TObject);
type
MyEnum = (Red, Green, Blue);
var
I: integer;
ch: char;
b: boolean;
col: TColor;
e: MyEnum;
f: TFont;
s: string;
si: Single;
p: pointer;
begin
{请参考Delphi帮助主题typecasts。
类型强制转化(如:Integer('A'))包括常量强制转化和变量强制转化。
常量强制转化:只有枚举类型和指针类型常量可以强制转化,而且不允许被赋值,这是个缺点;
变量强制转化:变量强制转化有自由,原则上可以把任何变量强制转化为任何类型,而且支持被赋值。
类和接口的强制转换要用as。}

//=============基本类型=============
//基本类型一般用带括号这种强制转换

//这些是枚举、指针类型常量,允许强制转换为任何类型
I := Integer('A');
ch:= Char(48);
b:= Boolean(0);
col:= TColor('A');
f:= TFont(Red);
si:= single(p);
//TFont(Red):= clRed; //常量不允许赋值[Error] Unit1.pas(55): Left side cannot be assigned to

//这些都不是枚举、指针类型常量,编译不通过!
//ch:= char('string'); //[Error] Unit1.pas(47): Invalid typecast
//f:= TFont(3.14); //[Error] Unit1.pas(48): Invalid typecast

//如果是变量那么理论上可以随意强制转换
e:= MyEnum(f);
Self:= TForm1(col);
TForm1(col):= nil; //变量可以赋值!
//e:= single(s); //不知道为什么字符串不可以?[Error] Unit1.pas(57): Incompatible types: 'MyEnum' and 'Single'

//=============类类型、接口类型=============
//类则一般先用is判断是不是这个类的子类对象再用as强制转化。

//(Form1 as TButton).Caption:= 'OK'; //因为TForm1类不是TButton类子类。[Error] Unit1.pas(29): Incompatible types: 'TButton' and 'TForm1'
//(Button1 as TForm).Caption:= 'OK'; //因为TButton类不是TForm1类子类。[Error] Unit1.pas(30): Incompatible types: 'TForm' and 'TButton'
if Form1 is TCustomForm then
(Form1 as TCustomForm).Caption:= 'OK';

TCustomForm(Form1).Caption:= 'OK'; //只要有这个属性就编译通过!
TButton(Form1).Caption:='OK';
TPanel(Form1).Caption:='OK';
TLabel(Form1).Caption:='OK';
TOpenDialog(Form1).FileName:= 'FooCast'; //编译通过,运行出内存访问错误!因为窗体无FileName属性

{
看得出编译器对as操作符进行了类继承关系判断,而带括号的强制转换则没有。比如上面的TOpenDialog
和TForm1根本没任何关系,但是强制转换成功!但是这种代码非常危险,编译器无法检测出毛病,一运行就
出内存访问错误。而TButton(Form1).Caption:='OK';编译运行都正常,这说明当用到两个类共有属性时
带括号的强制转换和as转换等效,否则发生运行期异常。

再看这两个语句到底什么区别?
TEdit(Object)
(Object As TEdit)

假如:Object: TMyObject;
..
TEdit(Object)
(Object As TEdit)
只有在TMyObject类是TEdit类子类,而且TMyObject类和TEdit类至少有一个相同的
属性、方法或事件时这两个语句等价,否则至少有一个出错,不等价。}
end;
 
我自己写代码测试得出的结果:

AS只能向同类或者父类转化,例如:(TButton As TButtonControl)不会有问题,但是
(TButton As TForm)则绝对会报错
TEdit(AnyOjbect)则没有这个限制,可以随意转换。
AS的限制更加多。
 
我自己搞定了。
谢谢各位的支持
 
后退
顶部