delphi - Genéricos: ¿Qué es una "restricción CONSTRUCTOR"?
generics delphi-2009 (2)
Hice un descendiente personalizado TObjectList diseñado para mantener subclases de una clase de objeto base. Se ve algo como esto:
interface
TMyDataList<T: TBaseDatafile> = class(TObjectList<TBaseDatafile>)
public
constructor Create;
procedure upload(db: TDataSet);
end;
implementation
constructor TMyDataList<T>.Create;
begin
inherited Create(true);
self.Add(T.Create);
end;
Quiero que cada nueva lista comience con un objeto en blanco. Es bastante simple, ¿verdad? Pero al compilador no le gusta. Dice:
"No se puede crear una instancia nueva sin la restricción CONSTRUCTOR en la declaración de parámetros de tipo" Solo puedo suponer que esto es algo relacionado con los genéricos. ¿Alguien tiene alguna idea de lo que está pasando y cómo puedo hacer que este constructor funcione?
Está intentando crear una instancia de T
través de T.Create
. Esto no funciona porque el compilador no sabe que su tipo genérico tiene un constructor sin parámetros (recuerde: esto no es un requisito). Para rectificar esto, tienes que crear una restricción de constructor, que se ve así:
<T: constructor>
o, en su caso específico:
<T: TBaseDatafile, constructor>
Solo una actualización rápida de una vieja pregunta ...
No necesita la restricción de constructor y también puede hacer esto en objetos con parámetros usando RTTI como este (usando RTTI o System.RTTI con XE2)
constructor TMyDataList<T>.Create;
var
ctx: TRttiContext;
begin
inherited Create(true);
self.Add(
ctx.
GetType(TClass(T)).
GetMethod(''create'').
Invoke(TClass(T),[]).AsType<T>
);
end;
Si tiene parámetros, simplemente agréguelos de esta manera
constructor TMyDataList<T>.Create;
var
ctx: TRttiContext;
begin
inherited Create(true);
self.Add(
ctx.
GetType(TClass(T)).
GetMethod(''create'').
Invoke(TClass(T),[TValue.From(''Test''),TValue.From(42)]).AsType<T>
);
end;