Delphi 中带有继承的流畅界面
Fluent interface with inheritance in Delphi
我有以下流畅的接口声明和实现该接口的 class:
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
有什么办法可以实现吗?
对上述接口和 classes 的任何类型的更改都是可以接受的(显然,将这两个接口合并为一个接口除外)。
你可以这样写:
s := (TStrDocWriter.Create
.Open
.Add('abc')
.Close as IStrDocWriter)
.SaveToString;
不,不是很好。这两个习语,流畅的接口和继承,根本就不能混在一起。
我有以下流畅的接口声明和实现该接口的 class:
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
有什么办法可以实现吗?
对上述接口和 classes 的任何类型的更改都是可以接受的(显然,将这两个接口合并为一个接口除外)。
你可以这样写:
s := (TStrDocWriter.Create
.Open
.Add('abc')
.Close as IStrDocWriter)
.SaveToString;
不,不是很好。这两个习语,流畅的接口和继承,根本就不能混在一起。