简体   繁体   中英

Fluent interface with inheritance in Delphi

I have following fluent interface declaration and class that implements that interface:

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;

And I can use above code like this:

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

I have to extend above interface by adding SaveToString function.

I don't want to add that method to original IDocWriter interface because it is not valid method for all interface implementations. So I have done following

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;

In order to use IStrDocWriter interface I have to write code

var
  Writer: IDocWriter;
  s: string;

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

But I would like to be able to use it without the need to declare Writer variable, something like following code (which, of course, cannot be compiled)

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

Is there any way to achieve that?

Any kind of changes to above interfaces and classes are acceptable (except, obviously, merging those two interfaces into one).

You can write it like this:

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

No, not very nice is it. These two idioms, fluent interfaces and inheritance, simply do not mix.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM