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;