Delphi面向对象编程的20条规则(By Marco Cantu)(rule 11-15)

类别:Delphi 点击:0 评论:0 推荐:

规则11:显示组件属性(Expose Components Properties)
       当你需要访问其他窗体的状态时,你不应该直接访问它的组件。因为这样会将其他窗体或其它类的代码和用户界面结合在一起,而用户界面往往是一个应用程序中最容易发生改变的部分。最好的方法是,为你需要访问的组件属性定义一个窗体属性。要实现这一点,可以通过读取组件状态的Get方法和设置组件状态的Set方法实现。
假如你现在需要改变用户界面,用另外一个组件替换现有的组件,那么你只需做的是修改与这个组件属性相关的Get方法和Set方法,而不必查找,修改所有引用这个组件的窗体和类的源码。详细实现方法请参见下面的代码:

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;

规则12:属性数组(Array Properties) 
       如果你需要处理窗体中的一系列变量,你可以定义一个属性数组。如果这些变量是一些对于窗体很重要的信息,你还可以把他们定义成窗体默认的属性数组,这样你就可以直接使用SpecialForm[3]来访问他们的值了。
       下面的代码显示了如何将一个listbox组件的项目定义成窗体默认的属性数组。

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)的好处之一就是当你设置或者读取属性的值时,你还可能有意想不到的收获。
       例如,你可以直接在窗体界面上拖拉组件,设置多个属性的值,调用特殊方法,立即改变多个组件的状态,或者撤销一个事件(如果需要的话)等等。

规则14:隐藏组件(Hide Components)
      
我经常听见那些面向对象编程的狂热追求者抱怨Delphi窗体中包含一些在published部分声明的组件,这是和面向对象思想的封装性原理不相符合的。他们确实提出了一个重要的议题,但是他们中的大多数人都没有意识到解决方法其实就在他们手边,完全不用重写Delphi代码,也不用转向其他语言。
        Delphi向窗体中添加的组件参照可以被移到private部分,使得其他窗体不能访问他们。如果你这样做,你就有必要设置一些指向组件的窗体属性(请参见规则11),并且使用它们来访问组件的状态。
        Delphi将所有的这些组件都放在published部分,这是因为使用这种方式能够保证这些域一定是在.DFM文件中创建的组件。当你改变一个组件的名称时,VCL能够自动地将这个组件对象与它在窗体中的参照关联起来。因为delphi使用RTTI和Tobject方法来实现这种功能,所以如果想要使用这种自动实现功能,就必须把参照放置在published部分(这也正是为什么delphi将所有的组件都放在published部分的缘故)。
       如果你想知道的更详细一点,可以参看下面的代码:

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)查找更加完善的程序。

 

本文地址:http://com.8s8s.com/it/it5391.htm