将接口添加到非接口派生对象

时间:2014-07-09 05:32:51

标签: delphi inheritance interface

我有以下问题,我无法完全理解。假设我有一些课程:

TClassA = class 
TClassB = class( TClassA ) 

IMyList = interface( IXList<TClassB> )
TMyList = class( TXList<TClassB>, IMyList )

TMyThing1 = class( TClassB )
TListOfMyThing1 = class( TMyList )

TMyThing2 = class( TClassB )
TListOfMyThing2 = class( TMyList )

TListOfMyThingLists = class( TXList<TMyList> )

基本上,我有一个基础对象(TClassB)和几个派生自它的类。我还有一个包含这些对象的基本列表对象(TMyList)。

每个派生对象都有一个派生自基础容器的容器。

最后,我有一个列表列表,我在其中添加了每个列表。

我们的想法是能够遍历列表列表,然后遍历每个列表并应用所有列表共有的方法:解析,验证,渲染等。

它编译好并运行......直到它关闭,当我得到几个GPF,并且内存转储显示大量的内存泄漏。我想这是在一个继承级别使用接口但不超出该接口的副作用(即,IMyList / TMyList)。

我难倒的地方是如何将接口添加到后两组类中。 TClassB派生自TObject,并且没有接口。我认为我需要的东西(至少是什么样的东西)是这样的:

IMyThing1 = interface( TClassB, IInterface )
TMyThing1 = class( TClassB, TInterfacedObject, IMyThing1 ) 

但这不合法! (这是多重继承。坏了!)

如果我只是使用从TClassB派生的合法资料:

IMyThing1 = interface( TClassB, IInterface )
TMyThing1 = class( TClassB, IMyThing1 ) 

编译器(DXE5)抱怨:

[dcc32 Error] x.pas(#): E2291 Missing implementation of interface method IInterface.QueryInterface
[dcc32 Error] x.pas(#): E2291 Missing implementation of interface method IInterface._AddRef
[dcc32 Error] x.pas(#): E2291 Missing implementation of interface method IInterface._Release

虽然在某处的杂草中#线已关闭。 (IOW,它实际上并没有告诉我错误的位置。我只能通过选择性地注释掉代码来确定。)

是否有必要为从非接口类派生的每个类显式实现这些接口函数,以便保持&#34;托管&#34;被管理错误的对象&#34;?

或许还有另一种方法不那么明显?

(这似乎是一个问题,主要是因为Borland-Inprise-CG-EMBT的人们对实施&#34;真正的&#34;多重继承有着基本的宗教反对意见,因为愚蠢的人可以用它做蠢事。 。)

顺便说一句,这只是为了让自动引用计数(ARC)添加到类中而进行的 LOT

注意:这可能是之前已经回答的问题,但我不知道如何对问题进行说明以使其显示在搜索中。

3 个答案:

答案 0 :(得分:3)

混合接口和非接口对象指针并不是一个好主意,特别是如果从非接口对象指针中检索接口。如果使用接口,则应该为所有内容使用接口,包括变量和内部容器。话虽这么说,为了使这段代码在不崩溃的情况下工作,您可能必须覆盖_AddRef()_Release()来禁用对实现接口的类的引用计数。例如,TComponent就是这样做的。

答案 1 :(得分:1)

另一个选择是自己实现缺少的方法,以便满足编译器。这里有一篇很棒的文章,详细信息如下:https://sergworks.wordpress.com/2010/11/24/delphi-interfaces-without-reference-counting/

或者,或许更好的是,只是继承自TSingletonImplementation - 它为您实现了所需的方法。

答案 2 :(得分:0)

我发现了一个派生自TClassA的类,它是一个TInterfacedClassA,我从中派生出了TClassB。

TInterfacedClassA = class
TClassB = class( TInterfacedClassA )

其余的,我这样做了:

IMyList = interface( IXList<TClassB> )
TMyList = class( TXList<TClassB>, IMyList )

IMyThing1 = interface( IInterface )
TMyThing1 = class( TClassB, IInterface )
IListOfMyThing1 = interface( IInterface )
TListOfMyThing1 = class( TMyList, IListOfMyThing1 )

IMyThing2 = interface( IInterface )
TMyThing2 = class( TClassB, IInterface )
IListOfMyThing2 = interface( IInterface )
TListOfMyThing2 = class( TMyList, IListOfMyThing2 )

TListOfMyThingLists = class( TXList<TMyList> )

类中的所有setter和getter都被更改为使用Ixxx类型而不是使用它们的Txxx类型,并且方法也被更改为传递并返回Ixxx类型而不是Txxx类型。

这是有效的,除了添加列表之外,我需要这样做:

TListOfMyThing1.Add( aItem : IMyThing1 ) : integer;
begin
    Result := inherited Add( aItem as TClassB );
end;

这对我来说似乎很奇怪,因为aItem实际上是从TClassB派生的。

也许我需要一个IClassB来代替IInterface派生其他接口?