首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么TGeneric<Base>和TGeneric<Descendant>类型不兼容?

为什么TGeneric<Base>和TGeneric<Descendant>类型不兼容?
EN

Stack Overflow用户
提问于 2009-11-06 13:57:31
回答 2查看 1.6K关注 0票数 13

我已经在Delphi 2010中开始使用泛型,但是在编译这段代码时遇到了一个问题:

代码语言:javascript
复制
TThreadBase = class( TThread )
...
end;

TThreadBaseList<T: TThreadBase> = class( TObjectList<T> )
...
end;

TDataProviderThread = class( TThreadBase )
...
end;

TDataCore = class( TInterfacedObject, IDataCore )
private
  FProviders: TThreadBaseList<TDataProviderThread>;
...
end;

然后我有一些嵌套的过程:

代码语言:javascript
复制
procedure MakeAllThreadsActive(aThreads: TThreadBaseList<TThreadBase>);
begin
...
end;

最后,我想在TDataCore类的代码中调用这个嵌套过程:

代码语言:javascript
复制
MakeAllThreadsActive(FProviders);

但是编译器不想编译它,它说('<>‘括号替换为'()'):

DCC错误LSCore.pas(494):E2010不兼容类型:“TThreadBaseList(TThreadBase)”和“TThreadBaseList(TDataProviderThread)”

我不明白,虽然TDataProviderThread是TThreadBase的后代。

我不得不用硬打字机来解决这个问题:

代码语言:javascript
复制
MakeAllThreadsActive(TThreadBaseList<TThreadBase>(FProviders));

有人知道编译器为什么说这个错误吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-11-06 14:02:19

TDataProviderThread是TThreadBase的后代,但TThreadBaseList<TDataProviderThread>不是TThreadBaseList<TThreadBase>的后代。这不是继承,而是所谓的协方差,尽管从直觉上看,它似乎是相同的东西,但它不是,而且必须单独支持。目前,Delphi并不支持它,尽管希望它在将来的版本中得到支持。

协方差问题的基本原因是:如果传递给它的函数期望一个TThreadBase对象的列表,而传递给它的是一个TDataProviderThread对象的列表,那么没有什么可以阻止它调用.Add并将其他的TThreadBase对象添加到不是TDataProviderThread的列表中,现在您遇到了各种各样的丑陋问题。您需要来自编译器的特殊技巧,以确保这不会发生,否则您将失去您的类型安全。

编辑:这里有一个可能的解决方案:将MakeAllThreadsActive变成一个通用方法,如下所示:

代码语言:javascript
复制
procedure MakeAllThreadsActive<T: TThreadBase>(aThreads: TThreadBaseList<T>);

或者你可以照乌韦·拉比的建议去做。两种都能用。

票数 22
EN

Stack Overflow用户

发布于 2009-11-06 14:01:08

类型

代码语言:javascript
复制
TList <TBase>

的父类型。

代码语言:javascript
复制
TList <TChild>

仿制药不能以那种方式使用。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1687755

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档