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