我有一個這樣的課程:
type
TCipher = class
private
public
function Encrypt(sText: String; Key: TObject): String; virtual; abstract;
function Decrypt(sText: String; Key: TObject): String; virtual; abstract;
class var
sName: String;
sDisplayName: String;
end;
TCipherClass = class of TCipher;
TCaesar = class(TCipher)
private
public
function Encrypt(sText: String; Key: TObject): String; override;
function Decrypt(sText: String; Key: TObject): String; override;
class var
sName: String;
sDisplayName: String;
end;
implementation
function TCaesar.Encrypt(sText: String; Key: TObject): String;
begin
end;
function TCaesar.Decrypt(sText: String; Key: TObject): String;
begin
end;
initialization
TCipher.sName := 'defaultName';
TCipher.sDisplayName := 'defaultDipsplay';
ShowMessage(TCipher.sName ' ' TCipher.sDisplayName);
TCaesar.sName := 'caesar';
TCaesar.sDisplayName := 'Caesar Cipher';
ShowMessage(TCaesar.sName ' ' TCaesar.sDisplayName);
end.
在其他地方,我有一個這樣TList的類:
var
lstCiphers: TList<TCipherClass>;
cipher: TCipherClass;
begin
lstCiphers := TList<TCipherClass>.Create;
lstCiphers.AddRange([TCaesar]);
for cipher in lstCiphers do
ShowMessage('In list: ' cipher.ClassName ' . ' cipher.sDisplayName);
end;
但這回傳defDipsplay而不是Caesar Cipher. 我認為這是我在串列中做錯的事情,因為當我直接從課堂上展示它時,它顯示得很好:
ShowMessage(TCipher.ClassName ' . ' TCipher.sDisplayName);
ShowMessage(TCaesar.ClassName ' . ' TCaesar.sDisplayName);
uj5u.com熱心網友回復:
您的變數宣告為class var,因此它們特定于宣告它們的每個類。您class宣告的變數TCaesar與 中的class變數具有相同的名稱TCipher,但是當您嘗試在運行時通過TCipherClass元類參考訪問這些變數時,編譯器不知道元類指的是哪個實際類,因此它可以在編譯時執行所有操作-time 是生成代碼來訪問TCipher-specific 變數,而不是TCaesar-specific 變數。
在這種情況下,我建議使用class virtual方法而不是class vars,然后每個類都可以override在運行時使用方法回傳不同的值。
type
TCipher = class
public
function Encrypt(sText: String; Key: TObject): String; virtual; abstract;
function Decrypt(sText: String; Key: TObject): String; virtual; abstract;
class function CipherName: String; virtual;
class function DisplayName: String; virtual;
end;
TCipherClass = class of TCipher;
TCaesar = class(TCipher)
public
function Encrypt(sText: String; Key: TObject): String; override;
function Decrypt(sText: String; Key: TObject): String; override;
class function CipherName: String; override;
class function DisplayName: String; override;
end;
implementation
function TCaesar.Encrypt(sText: String; Key: TObject): String;
begin
...
end;
function TCaesar.Decrypt(sText: String; Key: TObject): String;
begin
...
end;
class function TCipher.CipherName: String;
begin
Result := 'defaultName';
end;
class function TCipher.DisplayName: String;
begin
Result := 'defaultDipsplay';
end;
class function TCaesar.CipherName: String;
begin
Result := 'caesar';
end;
class function TCaesar.DisplayName: String;
begin
Result := 'Caesar Cipher';
end;
initialization
ShowMessage(TCipher.CipherName ' ' TCipher.DisplayName);
ShowMessage(TCaesar.CipherName ' ' TCaesar.DisplayName);
end.
var
lstCiphers: TList<TCipherClass>;
cipher: TCipherClass;
begin
lstCiphers := TList<TCipherClass>.Create;
lstCiphers.Add(TCaesar);
for cipher in lstCiphers do
ShowMessage('In list: ' cipher.ClassName ' . ' cipher.CipherName '.' cipher.DisplayName);
end;
uj5u.com熱心網友回復:
您已經重新宣告sName并sDisplayName在TCaesar其中隱藏了祖先TCipher類中的同名變數。只需洗掉該宣告,您就會得到您期望的行為。
TCaesar = class(TCipher)
private
public
function Encrypt(sText: String; Key: TObject): String; override;
function Decrypt(sText: String; Key: TObject): String; override;
end;
在sName和sDisplayName領域仍然會的成員TCaesar在這里,因為他們將被繼承TCipher。如果您在后代類中宣告具有相同名稱的新變數,那么當通過后代型別的參考直接參考時,它們將隱藏祖先變數。但是,當使用將物件視為祖先的變數時,您將改為讀取和寫入祖先的欄位。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/315584.html
標籤:德尔福
上一篇:在delphi中銷毀json陣列
