【问题标题】:Fluent interface with inheritance in DelphiDelphi中具有继承的流畅接口
【发布时间】:2015-01-24 12:35:46
【问题描述】:

我有以下流畅的接口声明和实现该接口的类:

type
  IDocWriter = interface
    ['{8CB5799A-14B1-4287-92FD-41561B237560}']
    function Open: IDocWriter;
    function Close: IDocWriter;
    function Add(const s: string): IDocWriter;
    function SaveToStream(Stream: TStream): IDocWriter;
  end;

  TDocWriter = class(TInterfacedObject, IDocWriter)
  public
    function Open: IDocWriter;
    function Close: IDocWriter;
    function Add(const s: string): IDocWriter;
    function SaveToStream(Stream: TStream): IDocWriter;
  end;

{ TDocWriter }

function TDocWriter.Open: IDocWriter;
begin
  Result := Self;
  // DoOpen
end;

function TDocWriter.Close: IDocWriter;
begin
  Result := Self;
  // DoClose
end;

function TDocWriter.Add(const s: string): IDocWriter;
begin
  Result := Self;
  // DoAdd
end;

function TDocWriter.SaveToStream(Stream: TStream): IDocWriter;
begin
  Result := Self;
  // DoSaveToStream
end;

我可以像这样使用上面的代码:

var
  Stream: TStream;
  ...
  TDocWriter.Create
    .Open
    .Add('abc')
    .Close
    .SaveToStream(Stream);

我必须通过添加SaveToString 函数来扩展上面的接口。

我不想将该方法添加到原始IDocWriter 接口,因为它不是所有接口实现的有效方法。所以我已经完成了以下操作

type
  IStrDocWriter = interface(IDocWriter)
    ['{177A0D1A-156A-4606-B594-E6D20818CE51}']
    function SaveToString: string;
  end;

  TStrDocWriter = class(TDocWriter, IStrDocWriter)
  public
    function SaveToString: string;
  end;

{ TStrDocWriter }

function TStrDocWriter.SaveToString: string;
begin
  Result := 'DoSaveToString';
end;

为了使用IStrDocWriter接口我必须写代码

var
  Writer: IDocWriter;
  s: string;

  Writer := TStrDocWriter.Create
    .Open
    .Add('abc')
    .Close;
  s := (Writer as IStrDocWriter).SaveToString;

但我希望能够在不需要声明Writer 变量的情况下使用它,类似于下面的代码(当然不能编译)

  s := TStrDocWriter.Create
    .Open
    .Add('abc')
    .Close
    .SaveToString;   // Undeclared identifier SaveToString

有什么方法可以实现吗?

对上述接口和类的任何更改都是可接受的(显然,将这​​两个接口合并为一个除外)。

【问题讨论】:

  • 整个设计在我看来是错误的。流利真是太糟糕了!
  • 请原谅我的好奇,但是这个接口与流畅的需求是自己造成的,还是来自实际的业务需求,如果是,如何产生?
  • @MartynA 这是自找的原因。接口,因为它是 ref-counted 并且不需要 try..finally 块。流畅,因为它消除了声明变量的需要,并且当你有较长的链时使代码更具可读性。它可以内联使用在创建文档或报告时通常可以拥有的其他混乱代码中。想象一下 TTextDocWriter、TRichTextDocWriter、TPdfDocWriter、TMetafileDocWriter……

标签: delphi delphi-xe4 fluent-interface


【解决方案1】:

你可以这样写:

s := (TStrDocWriter.Create
    .Open
    .Add('abc')
    .Close as IStrDocWriter)
    .SaveToString; 

不,不是很好。这两个习语,流畅的接口和继承,根本就不要混用。

【讨论】:

  • 看起来很不错,可以达到预期的目的。我知道 fluent 不适用于继承,但是...
  • 看起来是一个很好的例子,说明为什么我们需要 Delphi 中的界面助手。
  • @Stefan 你知道接口助手有没有 QC/QP 报告
  • @Dalija 不,但根据 Marco Cantù 的说法,他们正在观看用户的声音,并且有这样的要求:delphi.uservoice.com/forums/4433-language-features/suggestions/…
猜你喜欢
  • 2014-09-07
  • 1970-01-01
  • 1970-01-01
  • 2011-12-19
  • 1970-01-01
  • 2020-12-27
  • 1970-01-01
  • 2021-04-30
  • 1970-01-01
相关资源
最近更新 更多