property WindowState: TWindowState read FWindowState write SetWindowState;

{声明一个属性WindowState,它从字段FWindowState读取值,用方法SetWindowState保存值(方法SetWindowState在内部将值保存到字段FWindowState)}

property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy

{声明一个特殊的属性——事件OnDestroy,和上面的不同,OnDestroy的存取都是通过字段FOnDestroy进行的}

==================================

如果类的定义和类的使用者在同一个单元内,那么该类的所有成员无论位于哪个区域,对于使用者而言都是可见的。 一个类对于相同单元的其他类来说,类似于C++中的“友类”,其所有成员都可以被访问。因此,类成 员的可见性设置只是在它们位于不同单元时,才是有效的。这时候,区域内成员的可见性规定如下:

(1) private 域:总不可见。这个区域用来隐藏一些实现细节并防止使用者直接修改敏感信息,比如 容纳属性的存取字段和方法。 (2) protected:派生类可见。这样既可以起到private 域的作用,也能给派生类提供较大的灵活性。 该区域常被用来定义虚方法。 (3) public:总可见。通常用来放置构造、析构函数等供使用者调用的方法。 (4) published:总可见。而且这个区域的类成员有运行时类型信息,该区域通常用来放置供使用者 访问的属性和事件。 (5) automated:总可见。而且该域的成员具有自动化类型信息,用于创建自动化服务器。该关键字 已经不再使用,为向后兼容保留。

=====================================

我们发现字段Button1 和过程Button1Click 并没有被明确地放到哪个可见性区域中。那么这时候 它们的可见性按什么规则来确定呢?此时和编译指令$M 密切相关。 后面我们要讲:$M 用来控制编译器是否给类生成运行时类型信息。所以,在{$M+}状态,Button1 和Button1Click 被隐含指定到published 域;在{$M-}状态,则到public 域。 那么对于上面的TForm1 来说,因为它现在处在{$M+}状态,所以Button1 和Button1Click 实际上 被隐含指定到published 域。

=================================

从调用者角度可分为: ① 普通方法; ② 类方法。 普通方法只能被类实例(即对象)调用,而类方法不但可以被对象调用,还可以直接被类调用(比 如构造函数Create 和析构函数Destroy)。

。实现一个类方法时,要特别注意不要让它依赖 于任何实例信息,千万不要在类方法中存取字段、属性和普通方法。否则通过类而不是对象来调用它 时,将发生错误,因为此时并没有实例信息。

===================================

inherited 并不仅仅局限在子类覆盖后的虚方法中调用父类中被覆盖的方法,实际上,inherited 可以使用在任何地方、调用子类可见的任何父类方法(包括protected、public、published 等域的)。

===================================

③ 抽象方法。它是虚方法的特例,在虚方法声明后加上abstract 关键字构成,如: TParent = class procedure OneProc; virtual; abstract; function OneFun: Boolean; dynamic; abstract; end; 抽象方法和普通虚方法的区别: a. 抽象方法只有声明,没有实现;而虚方法必须有实现部分,哪怕没有实际代码而只有begin…end 头。 b.  抽象方法必须在子类中覆盖并实现后才用调用。因为没有实现的方法不能被分配实际地址,而 调用一个没有实际地址的方法显然是荒谬的。 所以,抽象方法也可以被称为纯虚方法。

如果一个类中含有抽象方法,那么这个类就成了抽象类,如TStrings 含有: procedure Clear; virtual; abstract; procedure Delete(Index: Integer); virtual; abstract; 等多个抽象方法。 抽象类是不应该直接用来创建实例的,因为一旦调用了抽象方法,将抛出地址异常,而我们很难 保证不在某些地方调用抽象方法。所以,尽管实例化抽象类是被允许的,却是应该避免的。 因此,抽象类一般都是中间类,实际使用的总是覆盖实现了抽象方法的子类。比如常用的字符串 列表类TStrings,我们总是使用它的子类而不是它本身来构造实例,如:

var Strs: TStrings; begin Strs := TStringList.Create; ⋯⋯ end;

========================================================

重载方法的几个特点: a. 可以分别是函数或者过程。因为在Delphi 中,可以将过程看做一个没有返回值的函数,一个函 数也可以当作过程调用。 b. 如果位于相同类中,都必须加上overload 关键字;如果分别在父类和子类中,那么父类的方法 可不加overload 而子类必须加overload。 c. 如果父类的方法是虚(virtual 或者dynamic)的,那么在子类中重载该方法时应该加上reintroduce 修饰字,否则会出现编译警告:“hides virtual method of base type”。当然只是编译时产生警告,如果你 不顾它的警告,坚持不加修饰字,对程序运行结果也不会造成影响。如: TParent = class procedure OneProc; virtual; end; TChild = class(TParent) procedure OneProc; reintroduce; overload; end; d. 在published 区不能出现多个相同的重载方法。如: TParent = class procedure OneProc; virtual; end; TChild = class(TParent) published procedure OneProc; reintroduce; overload; {和父类构成方法重载关系是可以的,因为在TChild的published区,只有一个OneProc方法,而下面两行企图重载AnotherProc则是没可能的,编译器不允许在published区出现 多个同名的方法} procedure AnotherProc(S: String); overload; procedure AnotherProc; overload; end;

===================================

消息方法。消息方法的作用是截获并处理特定的一个消息。它使用的声明关键字是message。如: TCustomForm = class(TScrollingWinControl) private procedure WMClose(var Message: TWMClose); message WM_CLOSE; ⋯⋯ end; TCustomForm 声明了一个消息方法WMClose,WMClose 的作用是捕获并处理消息WM_CLOSE。 当WM_CLOSE 消息到来时,方法WMClose 被自动调用。关于消息方法是如何被自动调用的,可以 参考“VCL 消息机制”的内容。 消息方法的规则命名:消息类名大写+‘_’+消息名(第一个字母大写,其余小写);当然这个规 则不是强制的,你可以任意命名它。 消息方法参数声明格式:var Message: 消息类型。消息类型可以是基本消息类型TMessage,也可 以是特定的消息类型(一般是规则消息方法名头部加‘T’),如上面的可以是TWMClose。特定消息类 型都是Delphi 预定义的,一般位于Messages 单元;一些和具体控件相关的消息类型则在该控件的定 义单元定义。 消息方法的实现类似下面的代码:   procedure TCustomForm.WMClose(var Message: TWMClose); begin {在本类中对消息作必要的处理} Close; {然后调用父类对该消息的处理代码} inherited; end;

==============================

绝大部分属性是可读也可写的,少部分是只读的。可读可写属性一般声明在published 区,供组件 用户在设计时存取属性值,只读属性一般声明在public 区,供运行时使用代码取值(典型的如

================================

(1)对于没有取值范围限制的属性,常常直接用字段来实现存取,如Controls 单元的片断: TControl = class(TComponent) ⋯⋯ private ⋯⋯ FHint: string; ⋯⋯ published ⋯⋯ property Hint: string read FHint write FHint; ⋯⋯ end. (2)当须要检查属性值的取值范围,或者须要执行一些附加操作时,通常采用方法来实现存取, 如TControl.Left 属性是这样声明的: property Left: Integer read FLeft write SetLeft; 方法SetLeft 实现如下: procedure TControl.SetLeft(Value: Integer); begin if Value <> FLeft then {如果新设定的值和原来的值相等,就没有必要执行下面的代码了} begin SetBounds(Value, FTop, FWidth, FHeight); {SetBounds内部执行FLeft := Value; SetBounds主要功能是根据新的Left、Top、 Width、Height属性值改变控件在界面上的显示位置} Include(FScalingFlags, sfLeft); end; end; TWinControl.Handle)。而只写属性在实际开发中几乎没有应用。

==========================

indexes 如果一个属性含有这个部分,那么该属性就具有数组的特点。indexes 就是存取数组元素时必须用 到的参数(我们将它理解为广义的数组元素索引)。一个很典型的例子是TCanvas 类定义的属性Pixels: TCanvas = class(TPersistent) private function GetPixel(X, Y: Integer): TColor; procedure SetPixel(X, Y: Integer; Value: TColor); public property Pixels[X, Y: Integer]: TColor read GetPixel write SetPixel; end; 当引用属性Pixels时,X和Y的值被自动传给GetPixel和SetPixel方法,这样GetPixel和SetPixel就可 以存取数组中有X和Y指定位置的元素了。

========================

接口和类的不同 (1)接口中只有方法、属性,没有字段。所以接口中的属性存取都必须通过方法。 (2)接口中的方法只有声明,没有实现。实现在类中完成。 (3)接口中的方法没有作用域。都是公开的,但是在类中则放到不同作用域。 (4)接口中的方法没有修饰字。可以认为它们都是抽象的。 (5)不能创建接口实例,要使用接口,必须在类中实现,通过类调用接口的方法。 (6)在类中必须声明和实现接口的所有方法。不像类继承中可以选择。 (7)接口中的方法在类中实现时,可以加virtual/dynamic、abstract 修饰,从而在子类中可以实现 覆盖。

再次深入理解delphi的类的更多相关文章

  1. 理解 Delphi 的类(十一) - 深入类中的方法[8] - 抽象方法与抽象类

    //抽象方法类似与接口; 在没有接口的年代 Delphi 是用抽象方法来模拟接口的; 我想它最终会被接口替代. {下面就定义了两个抽象方法} TMyClass = class(TObject)   p ...

  2. 理解 Delphi 的类(八) - 关于类的定义

      //标准语法   TMyClass1 = class(TObject)   end;   //如果是继承自 TObject 可以省略   TMyClass2 = class   end;   // ...

  3. 理解 Delphi 的类(十) - 深入方法[17] - 提前声明

    //要点17: 如果前面的方法要调用后面的方法, 后面的方法需要提前声明 function MyFunB(x: Integer): Integer; forward; {使用 forward 指示字提 ...

  4. 理解 Delphi 的类(十) - 深入方法[18] - 在接口区声明的方法都相当于提前声明了

    //要点18: 如果函数在接口区定义了, 就无需用 forward 提前声明了 unit Unit1; interface uses   Windows, Messages, SysUtils, Va ...

  5. 比较C++、Java、Delphi声明类对象时候的相关语法

    同学们在学习的时候经常会遇到一些问题,C++.Java.Delphi他们到底有什么不一样的呢?今天我们来比较C++.Java.Delphi声明类对象时候的相关语法.希望对大家有帮助! C++中创建对象 ...

  6. QMetaObject感觉跟Delphi的类之类有一拼,好好学一下

    提供了一堆原来C++没有的功能,比如反射什么的...但是可能还是没有Delphi的类之类更强,因为类之类可以“创建类”.可惜我学艺不精,对“类之类”也没有完全学会.先留个爪,有空把两个东西都好好学学, ...

  7. delphi 实体类 JSON 数组

    delphi 实体类 与JSON转换,序列化 TJson REST.JSON.pas   TJson.JsonToObjectTJson.ObjectToJsonString JsonEncode O ...

  8. Delphi 遍历类中的属性

    http://blog.csdn.net/easyboot/article/details/8004954 Delphi 遍历类中的属性 标签: delphistringbuttonclassform ...

  9. DELPHI学习---类和对象(五篇)

    Classes and objects(类和对象) 类(或者类类型)定义了一个结构,它包括字段(也称为域).方法和属性:类的实例叫做对象:类的字段.方法和属性被称为它的部件(components)或成 ...

随机推荐

  1. top N彻底解秘

    本博文内容: 1.基础Top N算法实战 2.分组Top N算法实战 3.排序算法RangePartitioner内幕解密 1.基础Top N算法实战 Top N是排序,Take是直接拿出几个元素,没 ...

  2. java对Ldap操作3

    "));    }}

  3. mysql常用总结

    用户管理mysql>use mysql;查看mysql> select host,user,password from user ;创建mysql> create user zx_r ...

  4. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(38)-Easyui-accordion+tree漂亮的菜单导航 系列目录 本节主要知识点是easyui ...

  5. 生成N个不重复的随机数(转)

    有25幅作品拿去投票,一次投票需要选16幅,单个作品一次投票只能选择一次.前面有个程序员捅了漏子,忘了把投票入库,有200个用户产生的投票序列为空.那么你会如何填补这个漏子? 当然向上级反映情况.但是 ...

  6. android 15 activity跳转

    从一个屏幕跳到另一个屏幕,一个activity跳转到另一个activity,Intent类用于组件之间传递数据和跳转,组件包括不仅activity. package com.sxt.day04_01; ...

  7. Qt 学习之路:Qt 简介

    Qt 是一个著名的 C++ 应用程序框架.你并不能说它只是一个 GUI 库,因为 Qt 十分庞大,并不仅仅是 GUI 组件.使用 Qt,在一定程度上你获得的是一个“一站式”的解决方案:不再需要研究 S ...

  8. JavaScript函数的四种存在形态

    函数的四种存在形态: 1.函数形态 2.方法形态 将函数赋值给某一个对象的成员,那么就称为方法 3.构造器形态 4.上下文形态   1.函数形态: var foo = function() { ale ...

  9. Android 中 SQLite 性能优化

    数据库是应用开发中常用的技术,在Android应用中也不例外.Android默认使用了SQLite数据库,在应用程序开发中,我们使用最多的无外乎增删改查.纵使操作简单,也有可能出现查找数据缓慢,插入数 ...

  10. Oracler读取各种格式的相关日期格式

    CREATE OR REPLACE Package Pkg_Stm_Date As     --Purpose:相关日期处理功能包          --获取某一天是第几周     Function ...