private function GetText:String; procedure SetText(const Value:String); public property Text:String; read GetText write SetText; function TformDialog.GetText:String; begin Result:=Edit1.Text; end; procedure TformDialog.SetText(const Value:String); begin Edit1.Text;=Value; end;
type TformDialog =class(TForm) private listItems:TlistBox; function GetItems(Index:Integer):String; procedure SetItems(Index:Integer:const Value:String); public property Items[Index:Integer]:string; end; function TFormDialog.GetItems(Index:Integer):string; begin if Index >=ListItems.Items.Count then raise Exception.Create(‘TformDialog:Out of Range’); Result:=ListItems.Items[Index]; end; procedure TformDialog.SetItems(Index:Integer;const alue:string); begin if Index >=ListItems.Items.Count then raise Exception.Create(‘TformDialog:Out of Range’); ListItems.Items[Index]:=Value; end;
规则13:使用属性的附加作用(Use Side-Effects In Properties) 请记住:使用属性而不是访问全局变量(参见规则10、11、12)的好处之一就是当你设置或者读取属性的值时,你还可能有意想不到的收获。 例如,你可以直接在窗体界面上拖拉组件,设置多个属性的值,调用特殊方法,立即改变多个组件的状态,或者撤销一个事件(如果需要的话)等等。
procedure Tcomponent.SetReference(Enable:Boolean); var Field:^Tcomponent; begin If Fowner<> nil then begin Field:=Fowner.FieldAddress(Fname); If Field<>nil then Field^:=Self else Field^:=nil; end; end;
上面的代码是Tcomponent类的SetReference方法,这个方法可以被InserComponent,RemoveComponent和SetName等方法调用。 当你理解了这一点后,你应该不难想到如果你将组件参照从published部分移到了private段,你将失去VCL的自动关联功能。为了解决这个问题,你可以通过在窗体的OnCreate事件中添加如下代码解决: Edit1:=FindComponent(‘Edit1’) as Tedit; 你接下来应该做的就是在系统中注册这些组件类,当你为他们注册过后就能使RTTI包含在编译程序中并且能够被系统所使用。当你将这些类型的组件参照移到private部分时,对于每一个组件类,你只需为他们注册一次。即使为他们注册不是一定必要的时候,你也可以这样做,因为对于RegisterClasses的额外调用有益无害。通常你应该在单元中负责生成窗体的初始化部分添加以下的代码: RegisterClass([TEdit]);
规则15:面向对象编程的窗体向导(The OOP Form Wizard) 为每一个窗体的每一个组件重复上述两个操作不仅十分的烦人,而且相当的浪费时间。为了避免额外的负担,我已经为此写了一个简单的向导程序。这个程序将会生成一些可以完成以上两步工作的代码,你需要做的仅仅是做几次复制和粘贴就行了。 遗憾的是这个向导程序不能自动将代码放置到单元中合适的地方,我目前正在修改这个向导程序,希望能实现这个功能。你可以到我的网站(www.marcocantu.com)查找更加完善的程序。