用delphi也可以象C++一样,通过定义类,派生,重写函数等,制作出具控件有多样性的程序来,下面是一个文本编辑器的编程笔记。 定义一个接口类(祖先),只有定义而没有任何实际内容的类,所有实际的控件的类都从它那里派生,它不能用来产生具体的控件。例子:unit IddEditor;interface uses Controls,Graphics; type Idd_Editor=classPublicFunction Save():boolean;Virtual;abstract;//纯虚函数,用于给继承者重写,并且没有任何内容Procedure Copy(); Virtual;abstract;Function CanCopy():boolean; Virtual;abstract;Procedure SelectAll(); Virtual;abstract;end; implementation end. 从接口类可以派生出具体一点的类了(父亲),(当然接口类也会派生出其他的类,这些类之间由于拥有共同的祖先,所以沟通成为可能)父亲把接口类的纯虚函数内容定义具体,同时也根据需要,生成一些新的虚函数,父亲把自己能做的都摆出来了,但是具体怎么做,留给儿子们去重写吧。例子:unit Editor; interface uses Controls,Graphics,Classes,IddEditor; type TddEditor=Class(Idd_Editor) Private m_FileName:string;//多了一个成员变量,用来记录文件名字 Protected Procedure OnEditorSelectionChange(Sender:Tobject);//这是这个类自己特有的函数 Function GetText():String;Virtual;abstract;//新增加的纯虚函数 Public Constructor Create(ParentCtrl:TwinControl);//构造函数,是必须的 Destructor Destroy(); //解构函数,也是必须的 Procedure DoSaveToFile(FileName:String);Virtual;abstract; Function Save():Boolean;Override; //保存函数,不定义不行,定义得太死也不行,所以增加一个纯虚函数DoSaveToFile给后代重写,算是保留一点灵活性。 end; implementation uses GlobalObject; {TddEditor} Constructor TddEditor.Create(ParentCtrl:TwinControl);beginend; Destructor TddEditor.Destroy();beginend; Procedure TddEditor.OnEditorSelectionChange(Sender:Tobject);beging_EditorEvent.OnEditorSelectionChange(sender);end; Function TddEditor.Save():Boolean;//Override;beginif m_FileName ='' then begin Result:=SaveAs(); Exit; end;DoSaveToFile(m_FileName);Result:=True;end; end. 好了,丑妇终需见家翁,最后派生定义一个具体化的类吧(儿子),这个类可是实际要变出实际控件来干活的,因此该定义就都得定义完,不能再偷懒了。例子:unit memoEditor; interface uses StdCtrls,Controls,Graphics,Classes,Dialogs,SysUtils,ExtCtrls,Math,Editor,IddEditor; type TddmemoEditor=Class(TddEditor)Private m_Edit:TMemo;//既然是TddmemoEditor,里面肯定是包含一个Memo了 Protected Function GetText():String;Override; Public Constructor Create(ParentCtrl:TwinControl); Destructor Destroy(); Procedure DoSavetoFile(FileName:String);Override; Function GetSelectionText():String;Override; Procedure Copy(); Override; Function CanCopy():boolean; Override; Procedure SelectAll(); Override; end; implementation uses GlobalObject; {TddmemoEditor} Function TddmemoEditor.GetText():String;//Override;beginend; Constructor TddmemoEditor.Create(ParentCtrl:TwinControl);beginm_Edit:=TMemo.Create(nil);//memo控件诞生了with m_Edit do begin Parent:=ParentCtrl; WordWrap:=False; Align:=AlClient; ScrollBars:=ssBoth; m_Edit.Font.Name:='宋体'; m_Edit.Font.Size:=12; if CanFocus() then SetFocus(); end;end; Destructor TddmemoEditor.Destroy();//Override;begininherited; //继承一下m_Edit.Free; //memo控件完成历史使命了m_Edit:=nil;end; Procedure TddmemoEditor.DoSavetoFile(FileName:String);//Override;beginm_Edit.Lines.SaveToFile(FileName);//把实际功能都传交MEMO干了end; Function TddmemoEditor.GetSelectionText():String;//Override;beginResult:=m_Edit.SelText;end; Procedure TddmemoEditor.Copy(); //Override;beginm_Edit.CopyToClipboard;end; Function TddmemoEditor.CanCopy():boolean; //Override;beginResult:=m_Edit.SelLength<>0;end; Procedure TddmemoEditor.SelectAll(); //Override; beginend; end. 要制作一个控件,还要派生两次,到底为什么不一下子就定义一个完整的类呢?就是为了所谓的多样性,例如突然间想改用其他文本容器做Editor,只需要定义一个TddmemoEditor的兄弟(儿子类),就可以了,爸爸和祖先都是不用动的,有些时候还很贪心的,想一会用TddmemoEditor,一会用它的兄弟,换来换去的,于是想到建一个制作控件的机器,程序依靠制作器,就可以制造出实际控件,不用自己建立。例子:unit EditorCtor; interface uses StdCtrls,Controls,Editor; typeTddEditorCtor=Class //Editor控件的制作工厂,可以制作很多种控件,但需要子孙自己定义。Protected Function DoCreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):Integer;virtual;abstract;Public Function CreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):integer;end; TddmemoEditorCtor=Class(TddEditorCtor) //派生一个MemoEditor控件的制作工厂,它就只能产生一种控件。Protected Function DoCreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):Integer;OverRide;end; implementation uses memoEditor, SettingMgr, GlobalObject ; {TddEditorCtor}Function TddEditorCtor.CreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):integer;beginResult:=DoCreateAnEditor(Editor,ParentCtrl);end; {TddMemoEditorCtor}Function TddmemoEditorCtor.DoCreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):Integer;beginEditor:=TddmemoEditor.Create(ParentCtrl);Result:=Integer(Editor<>nil);end; end. 程序中,需要产生控件实例时用以下命令: g_EditorCtor :TddEditorCtor=nil;//定义控件制作器,但是到底是那种制作器呢,这里还不明确。 m_Editor:TddEditor;//以父亲的名义定义一个控件,具体生成的是MemoEditor还是他的其他兄弟呢,看下面一句。 g_EditorCtor:=TddmemoEditorCtor.Create;//这里就明确了。只需要把TddmemoEditorCtor换成它的兄弟,就所有都跟着变化了,程序却还一样的照用,这里体现多样性的好处。 g_EditorCtor.CreateAnEditor(m_Editor,ParentCtrl);//由于g_EditorCtor实际是MemoEditorCtor,当然产生的控件是TddmemoEditor。

评论