繼承一個界面控件,給它增加功能,但繼承的類仍然用父類的名字

這個標題看起來有點不好理解。

問題和解決方法來自這裏:https://blog.grijjy.com/2018/01/26/mvvm-starter-kit-part-3-of-3/

問題簡述:

0. 傳統做法:繼承一個控件,取一個新的名字,然後把它安裝到 IDE 裏面,需要用的時候,從控件托盤裏把這個新做的控件找出來,拖到界面上。

1. FireMonkey 的控件,它的 Style 利用了控件的類名。如果新的類名,搞 Style 會比較麻煩。

2. 安裝一個新的控件到 IDE 裏面也比較麻煩。

解決辦法:

從原有控件繼承,但子類依然用原有控件的名字。設計時仍然從控件托盤拖原有控件到界面上。然後在 use 裏面加上對新的控件的單元的引用。編譯的程序,這個控件已經是增加了新功能的新控件。

實例:

我自己模仿這個方法,自己寫了一個測試程序,測試上述辦法是成功的。測試程序的做法如下:

1. 新起一個 FMX 工程,保存到一個目錄底下。這時候我們有一個 Form1。

2. 拖一個 TEdit 和 一個 TButton 到這個 Form1 上面,我們有了 Edit1 和 Button1;

3. 新建一個單元用於接口方法定義,如下:

unit MyIntf;

interface

uses System.SysUtils, System.Types, System.Classes;

type
  IMyTest = interface
    ['{6CCACE8D-9817-4561-9272-D3743B1090AC}']
    procedure Hello(Sender: TObject);
  end;

implementation

end.

4. 新建一個單元用於繼承的類的定義,如下:

unit MyControl;

interface

uses System.SysUtils, System.Types, System.Classes,
     FMX.Types, FMX.Controls, FMX.Edit,
     MyIntf;

type
  TEdit = class(FMX.Edit.TEdit, IMyTest)
  public
    procedure Hello(Sender: TObject);

  end;

implementation

{ TMyEdit }

procedure TEdit.Hello(Sender: TObject);
begin
  Self.Text := Self.Text + Sender.ClassName + ' - Hello';
end;

end.

注意上述代碼,繼承自 TEdit 的類,名字仍然是 TEdit。這裏要注意。它多了一個自己定義的接口。這裏爲它實現一個接口方法。

5. 在 Form1 的單元裏面,把這個 MyControl 單元的名字加到 use 的最後。這樣,之前拖過來的 TEdit 將會是 MyControl 裏面定義的這個,而不是 Delphi 原本的那個。我們在 Button1 的 OnClick 裏面可以測試調用它的接口,成功。說明確實是我們自己新繼承的這個。這樣,UI 設計的時候直接拖 Delphi 原本的控件過來,實際運行的時候它有新的功能。也無需專門爲了這個新功能的控件去另取一個類名再做 IDE 的控件安裝。省了很多事。

測試單元的代碼如下:

unit Unit1;
  //直接繼承一個 TEdit,爲繼承的 Edit 增加一個接口。但是,並不用新的類名,還是用原來的 TEdit 這個類名。
  //然後無需安裝新繼承的控件,仍然直接拖一個原來的 TEdit 過來放到 Form 上
  //然後在 Use 裏面,最後放上新繼承的類的聲明單元,注意順序,一定要放到最後
  //這樣,當程序運行,這個 TEdit 就已經有了新增加的接口。也就是說它的實例是新的類,而不是老的類。
  //2020-2-5
interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Edit,
  FMX.Controls.Presentation, FMX.StdCtrls, MyIntf, MyControl;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;     //直接拖過來的控件,雖然還是 TEdit,但因爲在 MyControl 單元裏重新聲明瞭相同名字的 TEdit,繼承了原來的 TEdit 爲它增加了一個接口,程序就能直接調用到這個接口了。
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
begin
  (Edit1 as IMyTest).Hello(Self);
end;

end.

 

發佈了116 篇原創文章 · 獲贊 17 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章