问题
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).
回答1:
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.
来源:https://stackoverflow.com/questions/28125514/fluent-interface-with-inheritance-in-delphi