delphi 子接口是否实现父接口_为什么我的班级实现子接口,而不实现其父接口?...

I found a (at least for me) unexpected behavior when using interface inheritance in Delphi.

I have this simple class and interface hierarchy:

+---------------+

| << IMyBase >> |

+---------------+

^

|

+---------------+

| << IMyIntf >> |

+---------------+

^

|

+---------+

| TMyObj |

+---------+

I wanted to declare a variable of type IMyBase. Create a TMyObj and assign it to my variable. IHMO this is normal OOP practice. But it turned out that it does not compile.

I Have also tried to declare a variable of type IMyIntf and check if it supports IMyBase, IMHO it should support it, but it doesn't.

Here is a simple test code:

program interface_inheritance;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils;

type

IMyBase = interface

['{CC7C61B8-3FBA-481F-AF0D-A93C603B5202}']

procedure Hello;

end;

IMyIntf = interface(IMyBase)

['{01CE01D9-A753-431C-A30E-64BAEC6C4E26}']

//

end;

TMyObj = class(TInterfacedObject, IMyIntf)

procedure Hello;

end;

{ TMyObj }

procedure TMyObj.Hello;

begin

Writeln('Hello World');

end;

var

b: IMyBase;

i: IMyIntf;

begin

(* // Compile Error E2010

b := TMyObj.Create;

b.Hello;*)

// Does not work as Expected

// Does not call Hello()

i := TMyObj.Create;

if Supports(i, IMyBase, b) then begin

// Why does i not support IMyBase ??

b.Hello;

end;

// Works but unsafe!

// Hard cast, without check.

i := TMyObj.Create;

b := IMyBase(i);

b.Hello;

// Works, of course!

i := TMyObj.Create;

i.Hello;

Readln;

end.

As you can see i have a valid class/interface structure. but some parts do not compile. and some do not execute as expected.

Why does b := TMyObj.Create; give an incompatible type error?

Why does Supports(i, IMyBase, b) returns false?

Is there another (better) way to solve such a problem? without a hard cast without check? (if i is IMyBase does not work, because interfaces do not support is operator.)

Is this valid Pascal/Delphi behavior or a bug? IMHO Supports() should return true. and TMyObj should be a valid IMyBase (and therefor be assignable).

解决方案

This might seem a little counter intuitive, but your class must declare that it implements the parent interface, too. Your class declaration must be like so:

TMyObj = class(TInterfacedObject, IMyBase, IMyIntf)

Danny Thorpe, a former Borland engineer, explained the rationale behind this behaviour in an answer to a related question:

If an implementing class does not declare that it supports an

inherited interface, then the class will not be assignment compatible

with variables of the inherited interface. The code sample you posted

should work fine (using the IChild interface), but if you try to

assign from an instance of TMyClass to a variable of IParent, then

you'll run into trouble.

The reason is because COM and ActiveX allow an implementation to

implement a descendent interface (your IChild) but deny the ancestor

of that interface (IParent). Since Delphi interfaces are intended to

be COM compatible, that's where this goofy artifact comes from.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值