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.