如何实现继承

时间:2013-05-12 15:18:44

标签: delphi oop

我有一个父类,可以有两个可能的子类:

  TEmailBaseAccount = class
    Connected: boolean;

    setting: TEmailAccountSettings;
    folders: TEmailAccountFolders;
    procedure Connect; virtual; abstract;
  end;

  TEmailIMAPAccount = class(TEmailBaseAccount)
    IdIMAP4: TIdIMAP4;
    OpenSSLHandler: TIdSSLIOHandlerSocketOpenSSL;

    procedure Connect; override;
  end;

  TlEmailPOP3Account = class(TEmailBaseAccount)
    IdPOP3: TIdIPOP3;
    OpenSSLHandler: TIdSSLIOHandlerSocketOpenSSL;

    procedure Connect; override;
  end;

我正在使用通用TList维护电子邮件帐户列表:

  TEmailAccountList = class(TList<TEmailBaseAccount>)
    procedure SaveToStream(Stream: TStream);
    procedure LoadFromStream(Stream: TStream);
    constructor Create(AOwner: TObject);
    destructor Destroy;
  end;

使用以下代码将电子邮件帐户添加到列表中:

procedure TEmailAccountList.LoadFromStream(Stream: TStream);
var
  a, c: Integer;
  e: TEmailBaseAccount;
begin
  c := ReadStreamInt(Stream);
  for a := 0 to c - 1 do
  begin
    e := TEmailBaseAccount.Create(FOwnerEmailEngine);  
    e.LoadFromStream(Stream);
    Add(e);
  end;

end;

procedure TEmailAccountList.SaveToStream(Stream: TStream);
var
  a, c: Integer;
  e: TEmailBaseAccount;
begin
  c := Count;
  WriteStreamInt(Stream, c);
  for a := 0 to Count - 1 do
    Items[a].SaveToStream(Stream);
end;

在运行时,我需要使用以下内容来区分两种类型的子类:

 if account is TEmailIMAPAccount then
  ...
 else if account is TEmailPOP3Account then
  ...

我确信我原来的类声明和TList声明不适合这个要求。在这种情况下需要进行哪些更改?

TIA。

2 个答案:

答案 0 :(得分:1)

你的类型声明绝对没问题。你的问题可能是当你从流中读取一个项目时,你不知道它是什么类型。你不能使用is,因为你还没有实例。

通过为每个实例的流写入类型代码来解决该问题。从流中读取时,请读取类型代码并使用它来确定要实例化的类型。

使用发布XML,JSON,YAML等的持久性框架,这种持久性流式传输非常容易。

答案 1 :(得分:0)

我只会将帐户属性(邮件帐户类型,用户凭据,服务器/端口/安全设置)写入文件,而不是序列化完整的,特定于高度实现的对象。

这允许在不破坏现有设置文件兼容性的情况下修改实现。

我甚至不会考虑if <object> is <class> ... else if <object> is <otherclass> ...解决方案。相反,定义一个简单的枚举类型TAccountType = (atPOP3, atIMAP),然后根据帐户的帐户类型属性在案例结构中进行分支,或使用Strategy pattern