我目前仍然遇到编译错误,我们公司中没有人可以提供帮助,而我很遗憾没有为SO或谷歌找到正确的搜索模式。
作为代码,我使用2个接口,继承和2个类,继承。 以下代码重现错误:
program Project22;
{$APPTYPE CONSOLE}
type
IStorageObject = interface(IInterface)
end;
TObjectStorage<T: IStorageObject> = class(TObject)
end;
IKeyStorageObject<TKey> = interface(IStorageObject)
end;
TKeyObjectStorage<TKey, T: IKeyStorageObject<TKey>> = class(TObjectStorage<T>)
end;
TImplementingClass<TKey> = class(TInterfacedObject, IKeyStorageObject<TKey>)
end;
begin
TKeyObjectStorage<Integer, TImplementingClass<Integer>>.Create;
end.
'TKeyObjectStorage'的编译错误是:
[DCC错误] Project22.dpr(11):E2514类型参数'T'必须支持接口'IStorageObject'
我认为,编译器没有正确识别类'TKeyObjectStorage'的参数T. 它应该是正确的,因为想要的Type'IKeyStorageObject'具有父类型IStorageObject。
为什么这不起作用?我究竟做错了什么?这在Delphi中是不可能的吗?
答案 0 :(得分:9)
<强>更新强>
原始问题出现了我发现的问题(见下文)。但是,我描述的修复程序适用于XE3及更高版本,但下面的程序不能在XE2中编译。因此,我得出结论,这是一个XE2泛型编译器错误。
无论如何,这是 Delphi XE2 的解决方法:
{$APPTYPE CONSOLE}
type
IStorageObject = interface(IInterface)
end;
TObjectStorage<T: IStorageObject> = class(TObject)
end;
IKeyStorageObject<TKey> = interface(IStorageObject)
end;
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>, IStorageObject> = class(TObjectStorage<T>)
end;
TImplementingClass<TKey> = class(TInterfacedObject, IStorageObject, IKeyStorageObject<TKey>)
end;
begin
TKeyObjectStorage<Integer, TImplementingClass<Integer>>.Create;
end.
原始回答
如果您提供了一个显示编译器错误的完整程序,那会更好。您需要尝试实例化一个对象以查看该错误。
但是,我想我已经复制了你的问题。所以我认为问题在于这段代码:
TKeyObjectStorage<TKey, T: IKeyStorageObject<TKey>> = ...
将通用约束应用于TKey
和T
。现在,显然您只希望将约束应用于T
,因此您需要编写:
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>> = ...
这是一个简短的程序,可以根据 Delphi XE3 中的更改进行编译:
{$APPTYPE CONSOLE}
type
IStorageObject = interface(IInterface)
end;
TObjectStorage<T: IStorageObject> = class(TObject)
end;
IKeyStorageObject<TKey> = interface(IStorageObject)
end;
TKeyObjectStorage<TKey; T: IKeyStorageObject<TKey>> = class(TObjectStorage<T>)
end;
TImplementingClass<TKey> = class(TInterfacedObject, IKeyStorageObject<TKey>)
end;
begin
TKeyObjectStorage<Integer, TImplementingClass<Integer>>.Create;
end.
这是一个非常细微的差别,将逗号更改为分号。通过重要标点编程从来没有太多乐趣。也就是说,你熟悉正式参数列表中逗号和分号之间的区别,因此在这里看到相同的区别不应该太令人惊讶。
documentation确实涵盖了这一点:
多种类型参数
指定约束时,可以将多个类型参数分开 分号,与参数列表声明一样:
type TFoo<T: ISerializable; V: IComparable>
与参数声明类似,可以对多个类型参数进行分组 在逗号列表中一起绑定到相同的约束:
type TFoo<S, U: ISerializable> ...
在上面的示例中,
S
和U
都绑定到ISerializable
约束