Interface 通过接口委托实现,不传递给子代
考虑这个接口及其实现Interface 通过接口委托实现,不传递给子代,interface,freepascal,delegation,Interface,Freepascal,Delegation,考虑这个接口及其实现 unit utest; interface {$MODE OBJFPC} type IIntfA = interface procedure writeA(); end; IIntfB = interface(IIntfA) procedure writeB(); end; TADelegateClass = class(TInterfacedObject, IIntfA) publ
unit utest;
interface
{$MODE OBJFPC}
type
IIntfA = interface
procedure writeA();
end;
IIntfB = interface(IIntfA)
procedure writeB();
end;
TADelegateClass = class(TInterfacedObject, IIntfA)
public
procedure writeA();
end;
TAClass = class(TInterfacedObject, IIntfA)
private
delegateA : IIntfA;
public
constructor create(const AInst : IIntfA);
destructor destroy(); override;
property A : IIntfA read delegateA implements IIntfA;
end;
TBClass = class(TAClass, IIntfB)
public
procedure writeB();
end;
implementation
procedure TADelegateClass.writeA();
begin
writeln('Implement IIntfA through delegation');
end;
constructor TAClass.create(const AInst : IIntfA);
begin
delegateA := AInst;
end;
destructor TAClass.destroy();
begin
inherited destroy();
delegateA := nil;
end;
procedure TBClass.writeB();
begin
writeln('Implement IIntfB');
end;
end.
以下程序将不会编译
program test;
{$MODE OBJFPC}
uses
utest;
var b : IIntfB;
begin
b := TBClass.create(TADelegateClass.create());
b.writeA();
b.writeB();
end.
免费Pascal(3.0.4版)抱怨
错误:找不到接口方法“writeA;”的匹配实现
在声明TBClass
的行中
当然,我可以通过在TAClass
或TBClass
中实现writeA
来成功编译它,并从那里调用TADelegateClass
的writeA
方法
TAClass
是通过接口委托来具体实现IIntfA
接口的,但是为什么TBClass
是TAClass
的后代,不被认为是IIntfA
接口的具体实现呢
TAClass
是通过
接口委托,但为什么TBClass
,它是TAClass
的后代,
是否不认为是IIntfA
接口的具体实现
简短回答:问题不在于IIntfA
,而在于IIntfB
不完整
长期回答:接口继承是C++ VTHEY继承,有时不直观。 在示例中:
IIntfB = interface(IIntfA)
procedure writeB();
end;
实际上可以写成
IIntfB = interface
procedure writeA();
procedure writeB();
end;
在实现多个接口时,不会重用公共部件。编译器通过实现方法设置各个表,例如:
TADelegateClass:
QueryInterface(IIntfA) = Self.vtable_IIntfA
vtable_IIntfA.writeA <- Self.writeA
TAClass:
QueryInterface(IIntfA) = delegateA.vtable_IIntfA
TBClass:
QueryInterface(IIntfA) = inherited delegateA.vtable_IIntfA
QueryInterface(IIntfB) = vtable_IIntfB
vtable_IIntfB.writeA <- (this is missing!)
vtable_IIntfB.writeB <- Self.writeB
遗憾的是,我不知道如何告诉编译器从另一个接口访问映射。FWIW,Delphi也有同样的缺陷/缺点
TBClass = class(TAClass, IIntfB)
public
procedure IIntfB.writeA = writeB;
// dummy method, shows IIntfB.writeA is missing