不同的约束
问题描述:
我有这样的原子乐观初始化类仿制药相结合:不同的约束
type
Atomic<T: IInterface> = class
type TFactory = reference to function: T;
class function Initialize(var storage: T; factory: TFactory): T;
end;
class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
tmpIntf: T;
begin
if not assigned(storage) then begin
tmpIntf := factory();
if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpIntf)^, nil) = nil then
PPointer(@tmpIntf)^ := nil;
end;
Result := storage;
end;
现在我想执行的对象相同的模式。
type
Atomic<T: class> = class
type TFactory = reference to function: T;
class function Initialize(var storage: T; factory: TFactory): T;
end;
class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
tmpIntf: T;
begin
if not assigned(storage) then begin
tmpIntf := factory();
if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpIntf)^, nil) = nil then
tmpIntf.Free;
end;
Result := storage;
end;
我可以在两个不同的类中做这两个,但我真的想把这两个初始化器放在同一个伞下。 IOW,我理想喜欢用这个作为
var
o: TObject;
i: IInterface;
Atomic<TObject>.Initialize(o, CreateObject);
Atomic<IInterface>.Initialize(i, CreateInterface);
我找不到任何好的解决方案。我得到的唯一想法是声明类为Atomic<T>
(没有约束),然后以某种方式(不知道如何)在运行时检查T的RTTI并相应地继续。
我不太喜欢这个想法,我正在寻找更好的方法。
答
看来你不能指定“类或接口”类型的约束。因此,最简单的解决方案似乎是放弃约束(您可以使用RTTI在运行时强制执行它)。
对于RTTI的方法,你可以使用TypeInfo
功能:
uses
..., TypInfo;
class function Atomic<T>.Initialize(var storage: T; factory: TFactory): T;
var
tmpT: T;
begin
if not assigned(PPointer(@storage)^) then begin
tmpT := factory();
if InterlockedCompareExchangePointer(PPointer(@storage)^, PPointer(@tmpT)^, nil) = nil then begin
case PTypeInfo(TypeInfo(T))^.Kind of
tkInterface:
PPointer(@tmpT)^ := nil;
tkClass:
TObject(tmpT).Free;
else
raise Exception.Create('Atomic<T>.Initialize: Unsupported type');
end;
end;
end;
Result := storage;
end;
答
一个强类型的解决方案是两个泛型类包装成另一个类为操作
type
Atomic = class
type
Intf<T: IInterface> = class
type TFactory = reference to function: T;
class function Initialize(var storage: T; factory: TFactory): T;
end;
Obj<T: class> = class
type TFactory = reference to function: T;
class function Initialize(var storage: T; factory: TFactory): T;
end;
end;
提供公共的命名空间
用法于:
var
o: TObject;
i: IInterface;
Atomic.Obj<TObject>.Initialize(o, CreateObject);
Atomic.Intf<IInterface>.Initialize(i, CreateInterface);
+0
这也是一个不错的解决方案! –
这似乎工作正常,谢谢! – gabr
欢迎,@ gabr,我很高兴能帮上忙! –