Delphi笔记(整理)-类

一个类声明有如下格式
type className = class (ancestorClass)
memberList
end;

在类声明中,方法看起来就像函数(或过程)头,而没有函数(或过程)体。方法的定义出现在程序的
其它地方。比如,这里是Classes 单元中TMemoryStream 类的声明
type
TMemoryStream = class(TCustomMemoryStream)
private
FCapacity: Longint;
procedure SetCapacity(NewCapacity: Longint);
protected
function Realloc(var NewCapacity: Longint): Pointer; virtual;
property Capacity: Longint read FCapacity write SetCapacity;
public
destructor Destroy; override;
procedure Clear;
procedure LoadFromStream(Stream: TStream);
procedure LoadFromFile(const FileName: string);
procedure SetSize(NewSize: Longint); override;
function Write(const Buffer; Count: Longint): Longint; override;
end;

除了TObject,System 单元还声明了一个类引用类型TClass。

类和它的祖先类是赋值兼容的,所以,某个类类型的变量能引用它的任何子类类型的实例。

除了类类型,你可以使用如下语法声明一个object 类型
type objectTypeName = object (ancestorObjectType)
memberList
end;

Object 类型不能有published 成员。因为object 类型不是从TObject 继承,它们没有内置的构造函数和析构函数,也没有其它方法。
你能使用New 过程创建Object 类型的实例,并使用Dispose 过程销毁它们,你也可以像使用记录一样,采用简
单方式声明object 类型的变量。Object 类型只是为了向后兼容性,不推荐使用它们。

类的每个成员都有一个称为可见性的属性,用下面的关键字之一来表示它:private、protected、public、published 和automated。
private表示最小程度的访问能力,protected 表示中等程度的访问能力,public、published 和automated 表示最大程度的访问能力。

若声明一个成员时没有指定其可见性,则它和前面的成员拥有相同的可见性;若在类声明的开始没有指
定可见性,当在{$M+}状态下编译类时(或者继承自一个在{$M+}状态下编译的类),它的默认可见性是
published,否则,它的可见性是public。

通过重新声明,你可以在派生类中增大一个成员的可见性,但你不能降低它的可见性。比如,一个protected
属性在派生类中能被改变为public,但不能改为private。还有,published 成员在子类中不能改为public。

若声明一个类时以class 和分号结束,也就是有下面的格式,
type className = class;
在class 后面没有列出父类,也没有成员列表,这是一个forward 声明。Forward 声明的类必须在同一个
声明区域进行定义声明,换句话说,在forward 声明和它的定义声明之间除了类型声明外,不能有任何
其它内容。

虽然类声明既可以出现在单元的interface 部分,也可以出现在implementation 部分,但类方法的实现(定
义声明)必须出现在implementation 部分。

。指示字应当只出现在类声明中,并且以下面的顺序列出:
reintroduce; overload; binding; calling convention; abstract; warning
这里,binding 是virtual、dynamic 或override;calling convention 是register、pascal、cdecl、stdcall 或
safecall;warning 是platform、deprecated 或library。

关键字inherited 在实现多态行为时扮演着特殊角色,它出现在方法定义中,后面跟一个标志符或者不跟。

方法分为静态方法(默认)、虚方法和动态方法。虚方法和动态方法能被覆盖,它们可是是抽象的。

方法默认是静态的。

要实现虚方法或动态方法,在声明时包含virtual 或dynamic 指示字。不像静态方法,虚方法和动态方
法能在派生类中被覆盖。当调用一个被覆盖的方法时,类或对象的实际类型决定了哪种实现被调用(运
行时),而不是它们被声明的类型。
要覆盖一个方法,使用override 指示字重新声明它就可以了。声明被覆盖的方法时,它的参数的类型和
顺序以及返回值(若有的话)必须和祖先类相同。

只有虚方法和动态方法能被覆盖,但是,所有方法都能被重载

虚方法和动态方法在语义上是相同的,唯一的不同是在运行时决定方法调用的实现方式上,虚方法在速
度上进行了优化,而动态方法在代码大小上做了优化。

在声明方法时,如果它和继承的方法具有相同的名称和参数,但不包含override,则新方法仅仅是隐藏
了继承下来的方法,并没有覆盖它。这样,两个方法在派生类中都存在,方法名是静态绑定的。

reintroduce 指示字告诉编译器,当隐藏一个先前声明的虚方法时,不给出警告信息。比如,
procedure DoSomething; reintroduce; // 父类也有一个DoSomething 方法
当要使用新方法隐藏继承下来的虚方法时,使用reintroduce 指示字。

抽象方法是虚方法或动态方法,并且在声明它的类中没有实现,而是由它的派生类来实现。声明抽象方
法时,必须在virtual 或dynamic 后面使用abstract 指示字。比如,
procedure DoSomething; virtual; abstract;
只有当抽象方法在一个类中被覆盖时,你才能使用这个类或它的实例进行调用。

一个方法可以使用overload 指示字来重新声明,此时,若重新声明的方法和祖先类的方法具有不同的参
数,它只是重载了这个方法,并没有隐藏它。当在派生类中调用此方法时,依靠参数来决定到底调用哪
一个。
若要重载一个虚方法,在派生类中重新声明时使用reintroduce 指示字。

在一个类中,你不能以相同的名字公布(published)多个重载的方法,维护RTTI 信息要求每一个公布
的成员具有不同的名字。

作为属性读写限定符的方法不能被重载。
实现重载的方法时,必须重复列出类声明时方法的参数列表。

按惯例,构造函数通常命名为Create
constructor Create;
constructor Create(AOwner: TComponent);

Message 方法用来响应动态分派的消息。Message 方法在各个平台上都是支持的,VCL 使用message 方
法来响应Windows 消息,CLX 不使用message 方法来响应系统事件。

比如,在Windows 下:
type
TTextBox = class(TCustomControl)
private
procedure WMChar(var Message: TWMChar); message WM_CHAR;
...
end;

消息处理函数很少直接调用,相反,消息是通过继承自TObject 的Dispatch 方法来分派给对象的。
procedure Dispatch(var Message);
传给Dispatch 的参数Message 必须是一个记录,并且它的第一个字段是Cardinal 类型,用来存储消息号
码。
Dispatch 按类的层次结构向后搜索(从调用对象所属的类开始),它将调用和传给它的消息具有相同号码
的message 方法。若没有发现指定号码的message 方法,Dispatch 调用DefaultHandler。

比如,给定下面的声明
property Color: TColor read GetColor write SetColor;
GetColor 方法必须被声明为:
function GetColor: TColor;
SetColor 方法必须被声明为下面之一:
procedure SetColor(value: TColor);
procedure SetColor(const value: TColor);
(当然,SetColor 的参数名不必非得是value。)

数组属性是被索引的属性,它们能表示像下面的一些事物:列表中的条目、一个控件的子控件和位图中
的象素等等。
声明数组属性时包含一个参数列表,它指定索引的名称和类型,比如,
property Objects[Index: Integer]: TObject read GetObject write SetObject;
property Pixels[X, Y: Integer]: TColor read GetPixel write SetPixel;
property values[const Name: string]: string read Getvalue write Setvalue;

定义数组属性时可以在后面使用default 指示字,此时,数组属性变成类的默认属性。
若一个类有默认属性,你能使用缩写词object[index]来访问这个属性,它就相当于object.property[index]。

索引限定符能使几个属性共用同一个访问方法来表示不同的值。
若一个属性有索引限定符,它的读写限定符必须是方法而不能是字段。

可选指示字stored、default 和nodefault 被称为存储限定符,它们对程序的行为没有影响,但决定了RTTI
的维护方式,它们决定是否把公布属性的值存储到窗体文件中。

stored 指示字后面必须跟True、False、Boolean 类型的字段名或者一个返回Boolean 值的无参数方法。
比如,
property Name: TComponentName read FName write SetName stored False;
若一个属性没有stored 指示字,就相当于指定了stored True。
default 指示字后面必须跟随一个和属性具有相同类型的常量,比如,
property Tag: Longint read FTag write FTag default 0;
要覆盖一个继承下来的默认值而不指定新值,使用nodefault 指示字。default 和nodefault 只支持有序类
型和集合类型(当它的基础类型是有序类型,并且上下边界都在0 到31 之间时)。若声明属性时没有使
用default 或者nodefault,它被当作nodefault 看待。对于实数、指针和字符串,它们分别有隐含的默认
值0、nil 和 ’ ’(空串)

声明时没有指定类型的属性称为属性覆盖,它允许你改变一个属性继承下来的可见性或限定符。

类引用类型有时称为元类,用如下的构造形式表示 class of type

每个类从TObject 继承了两个分别叫做ClassType 和ClassParent 的方法,前者返回对象的类引用,后者
返回对象的父类类引用。这两个方法的返回值都是TClass(这里TClass = class of TObject)类型,它们
能被转换为更加明确的类型。每个类还继承了一个叫做InheritsFrom 的方法,它测试调用的对象是否从
一个指定的类派生而来(如果对象是类的一个实例,结果如何?)。这些方法被is 和as 运算符使用,很
少直接调用它们。

is 运算符执行动态类型检查,用来验证运行时一个对象的实际类型。
object is class

as 运算符执行受检查的类型转换。表达式
object as class

类方法是作用在类而不是对象上面的方法(不同于构造函数)。类方法的定义必须以关键字class 开始,
比如,
type
TFigure = class
public
class function Supports(Operation: string): Boolean; virtual;
class procedure GetInfo(var Info: TFigureInfo); virtual;
...
end;
类方法的定义部分也必须以class 开始,比如,
class procedure TFigure.GetInfo(var Info: TFigureInfo);
begin
...
end;

<Leo>类方法类似C++/C#里的static成员????

类方法既可以通过类引用来调用,也可以使用对象,当使用后者时, Self 值等于对象所属的类。

要创建一个异常对象,在raise 语句中调用异常类的构造函数。比如,
raise EMathError.Create;
通常,raise 语句的格式是
raise object at address
这里,object 和at address 都是可选的。

异常在try...except 语句中被处理,比如,
try
X := Y/Z;
except
on EZeroDivide do HandleZeroDivide;
end;

SysUtils 单元声明了几个标准例程来处理异常,它们包括ExceptObject、ExceptAddr 以及ShowException。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值