用delphi也可以象C++一样,通过定义类,派生,重写函数等,制作出具控件有多样性的程序来,下面是一个文本编辑器的编程笔记。
定义一个接口类(祖先),只有定义而没有任何实际内容的类,所有实际的控件的类都从它那里派生,它不能用来产生具体的控件。例子:
unit IddEditor;
interface
uses Controls,Graphics;
type
Idd_Editor=class
Public
Function 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);
begin
end;
Destructor TddEditor.Destroy();
begin
end;
Procedure TddEditor.OnEditorSelectionChange(Sender:Tobject);
begin
g_EditorEvent.OnEditorSelectionChange(sender);
end;
Function TddEditor.Save():Boolean;//Override;
begin
if 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;
begin
end;
Constructor TddmemoEditor.Create(ParentCtrl:TwinControl);
begin
m_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;
begin
inherited; //继承一下
m_Edit.Free; //memo控件完成历史使命了
m_Edit:=nil;
end;
Procedure TddmemoEditor.DoSavetoFile(FileName:String);//Override;
begin
m_Edit.Lines.SaveToFile(FileName);//把实际功能都传交MEMO干了
end;
Function TddmemoEditor.GetSelectionText():String;//Override;
begin
Result:=m_Edit.SelText;
end;
Procedure TddmemoEditor.Copy(); //Override;
begin
m_Edit.CopyToClipboard;
end;
Function TddmemoEditor.CanCopy():boolean; //Override;
begin
Result:=m_Edit.SelLength<>0;
end;
Procedure TddmemoEditor.SelectAll(); //Override;
begin
end;
end.
要制作一个控件,还要派生两次,到底为什么不一下子就定义一个完整的类呢?就是为了所谓的多样性,例如突然间想改用其他文本容器做Editor,只需要定义一个TddmemoEditor的兄弟(儿子类),就可以了,爸爸和祖先都是不用动的,有些时候还很贪心的,想一会用TddmemoEditor,一会用它的兄弟,换来换去的,于是想到建一个制作控件的机器,程序依靠制作器,就可以制造出实际控件,不用自己建立。例子:
unit EditorCtor;
interface
uses StdCtrls,Controls,Editor;
type
TddEditorCtor=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;
begin
Result:=DoCreateAnEditor(Editor,ParentCtrl);
end;
{TddMemoEditorCtor}
Function TddmemoEditorCtor.DoCreateAnEditor(Var Editor:TddEditor;ParentCtrl:Twincontrol):Integer;
begin
Editor:=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。
评论