David が指摘したように、存在しない基本クラスのメソッドを参照することはできません。
クラス ヘルパーを使用すると、質問を別の方法で解決できます。最初のクラスのヘルパーは関数をTBaseClassHelper
追加し、2 番目のクラスのヘルパーも同様に追加します。この 2 番目の関数の実装を見てください。を呼び出します。SaveToText
TDerivedClassHelper
SaveToText
inherited SaveToText
更新 2
SaveTo
OP は、実装ごとに個別のユニットを必要としていました。David と Arioch によるコメントの助けを借りて、クラス ヘルパーは他のクラス ヘルパーから継承できることがわかりました。完全な例を次に示します。
unit uClasses;
type
TBaseClass = class
ID: Integer;
Name: String;
end;
TDerivedClass = class(TBaseClass)
Age: Integer;
Address: String;
end;
unit uClasses_Text;
uses uClasses,uClasses_SaveToText,uClasses_SaveToIni,uClasses_SaveToDB;
type
ITextable = interface
function SaveToText: string;
function SaveToIni: string;
function SaveToDB: string;
end;
// Adding reference counting through an interface, since multiple inheritance
// is not possible (TInterfacedObject and TBaseClass)
TBaseClass_Text = class(TBaseClass, IInterface, ITextable)
strict private
FRefCount: Integer;
protected
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
TDerivedClass_Text = class(TDerivedClass, IInterface, ITextable)
strict private
FRefCount: Integer;
protected
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
function _AddRef: Integer; stdcall;
function _Release: Integer; stdcall;
end;
implementation
uses Windows;
function TBaseClass_Text.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
function TBaseClass_Text._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TBaseClass_Text._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
function TDerivedClass_Text.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if GetInterface(IID, Obj) then
Result := 0
else
Result := E_NOINTERFACE;
end;
function TDerivedClass_Text._AddRef: Integer;
begin
Result := InterlockedIncrement(FRefCount);
end;
function TDerivedClass_Text._Release: Integer;
begin
Result := InterlockedDecrement(FRefCount);
if Result = 0 then
Destroy;
end;
unit uClasses_SaveToText;
interface
uses uClasses;
type
TBaseClassHelper = class helper for TBaseClass
function SaveToText: string;
end;
TDerivedClassHelper = class helper for TDerivedClass
function SaveToText: string;
end;
implementation
function TBaseClassHelper.SaveToText: string;
begin
Result := 'BaseClass Text info';
end;
function TDerivedClassHelper.SaveToText: string;
begin
Result := inherited SaveToText;
Result := Result + ' DerivedClass Text info';
end;
unit uClasses_SaveToIni;
interface
Uses uClasses,uClasses_SaveToText;
type
TBaseClassHelperIni = class helper(TBaseClassHelper) for TBaseClass
function SaveToIni: string;
end;
TDerivedClassHelperIni = class helper(TDerivedClassHelper) for TDerivedClass
function SaveToIni: string;
end;
implementation
function TBaseClassHelperIni.SaveToIni: string;
begin
Result := 'BaseClass Ini info';
end;
function TDerivedClassHelperIni.SaveToIni: string;
begin
Result := inherited SaveToIni;
Result := Result + ' DerivedClass Ini info';
end;
unit uClasses_SaveToDB;
interface
Uses uClasses,uClasses_SaveToText,uClasses_SaveToIni;
Type
TBaseClassHelperDB = class helper(TBaseClassHelperIni) for TBaseClass
function SaveToDB: string;
end;
TDerivedClassHelperDB = class helper(TDerivedClassHelperIni) for TDerivedClass
function SaveToDB: string;
end;
implementation
function TBaseClassHelperDB.SaveToDB: string;
begin
Result := 'BaseClass DB info';
end;
function TDerivedClassHelperDB.SaveToDB: string;
begin
Result := inherited SaveToDB;
Result := Result + 'DerivedClass DB info';
end;
program TestClasses;
uses
uClasses in 'uClasses.pas',
uClasses_Text in 'uClasses_Text.pas',
uClasses_SaveToText in 'uClasses_SaveToText.pas',
uClasses_SaveToIni in 'uClasses_SaveToIni.pas',
uClasses_SaveToDB in 'uClasses_SaveToDB.pas';
var
Textable: ITextable;
begin
Textable := TDerivedClass_Text.Create;
WriteLn(Textable.SaveToText);
WriteLn(Textable.SaveToIni);
WriteLn(Textable.SaveToDB);
ReadLn;
end.
更新 1
のいくつかの側面を実装する必要性についてのコメントを読んでSaveToText
、単純なピギーバック ソリューションを提案します。
type
ITextable = interface
function SaveToText: String;
end;
TMyTextGenerator = class(TInterfacedObject,ITextable)
private
Fbc : TBaseClass;
public
constructor Create( bc : TBaseClass);
function SaveToText: String;
end;
{ TMyTextGenerator }
constructor TMyTextGenerator.Create(bc: TBaseClass);
begin
Inherited Create;
Fbc := bc;
end;
function TMyTextGenerator.SaveToText: String;
begin
Result := IntToStr(Fbc.ID) + ' ' + Fbc.Name;
if Fbc is TDerivedClass then
begin
Result := Result + ' ' + IntToStr(TDerivedClass(Fbc).Age) + ' ' +
TDerivedClass(Fbc).Address;
end;
end;
TSaveToIni、TSaveToDB などを同じパターンで別のユニットに実装します。