Generics: Что такое «ограничение КОНСТРУКТОРА»? - PullRequest
9 голосов
/ 20 декабря 2008

Я сделал собственный потомок TObjectList, предназначенный для хранения подклассов базового класса объектов. Это выглядит примерно так:

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;

Я хочу, чтобы каждый новый список начинался с одного пустого объекта. Это довольно просто, верно? Но компилятору это не нравится. Там написано:

"Невозможно создать новый экземпляр без ограничения CONSTRUCTOR в объявлении параметра типа" Я могу только предположить, что это что-то связанное с дженериками. Кто-нибудь знает, что происходит и как я могу заставить этот конструктор работать?

Ответы [ 2 ]

17 голосов
/ 20 декабря 2008

Вы пытаетесь создать экземпляр T через T.Create. Это не работает, потому что компилятор не знает, что у вашего универсального типа есть конструктор без параметров (помните: это не обязательное требование). Чтобы исправить это, вы должны создать ограничение конструктора, которое выглядит так:

<T: constructor>

или, в вашем конкретном случае:

<T: TBaseDatafile, constructor>
2 голосов
/ 05 сентября 2011

Просто быстрое обновление старого вопроса ..

Вам не нужно ограничение конструктора, и вы также можете сделать это для объектов с параметрами, используя RTTI, например, (используя RTTI или System.RTTI с 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;

Если у вас есть параметры, просто добавьте их вот так

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;
...