Создать объект для универсального списка объектов - PullRequest
4 голосов
/ 06 августа 2010

Я не уверен, возможно ли это в Delphi.Я оглянулся и не могу найти ответ (Пример или недействительность, что это невозможно):

У меня есть универсальный класс списка, и я хочу создать экземпляр универсального типа.Например:

type
  TTypeA = class(TObject);

procedure Test;
var
  MyList: TobjectList<TTypeA>;
  NewListObject: TTypeA;
begin
  MyList := TObjectList<TTypeA>.Create;
  NewListObject := MyList.xxx //what to put on the xxx
end;

Можно ли создать функцию xxx, которая создает новый объект типа TTypeA?

@ jeroen: спасибо за ответ ниже.Однако я забыл важную деталь в своем вопросе:

Я бы хотел, чтобы этот код работал и для любого другого типа, поэтому без предварительного знания о типе T для TObjectList.Я мог бы создать следующие списки:

MyList: TObjectList<TCar>;
MyList: TObjectList<TBike>;

Не зная, содержит ли MyList TCar или TBike (оба получены из одного базового класса и имеют одинаковые конструкторы), я хочу добавить новый элемент в MyList.

И с предложением Уве Раабе я столкнулся со следующей проблемой:

Я изменил свой класс на

TMyObjectList<T:class, constructor> = class(TMyBaseObjectList<T>)

, где TMyBaseObjectList определен как

TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList)

Теперь я получаю сообщение об ошибке: Тип параметра 'T' не совместим с типом 'T: TMyBaseObject'

Ответы [ 5 ]

3 голосов
/ 06 августа 2010

Как вы знаете тип, почему бы вам просто не написать

NewListObject := TTypeA.Create;
MyList.Add(NewListObject);

Это был бы естественный способ сделать это здесь. (я только что получил ответ от аналогичного ответа Йероена)

Если вы хотите, чтобы контейнер создавал объект, вам нужно создать класс-потомок, который знает немного больше об универсальном типе, чтобы создать экземпляр. Здесь может помочь конструктор ограничение .

type
  TMyObjectList<T:class, constructor> = class(TObjectList<T>)
  public
    function NewObject: T;
  end;

function TMyObjectList<T>.NewObject: T;
begin
  result := T.Create;
end;

Примечание: Это будет работать, только если фактический тип имеет конструктор без параметров с именем Create .

Обновление : это поможет

  TMyObjectList<T:constructor, TMyBaseObject> = class(TObjectList<T>)
  public
    function NewObj: T;
  end;
0 голосов
/ 06 августа 2010

Насколько я знаю, вы можете использовать конструктор без параметров только внутри универсального класса для вашего универсального типа.

Одним из способов решения этой проблемы является использование анонимного метода для создания объекта, но это означает, что вам потребуется создать много методов.

Что касается другой проблемы ...

TMyObjectList<T:class, constructor> = class(TMyBaseObjectList<T>)
TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList)

Я считаю, что правильное объявление будет

TMyObjectList<T:TMyBaseObject, constructor> = class(TMyBaseObjectList<T>)
TMyBaseObjectList<T:TMyBaseObject> = class(TObjectList)

TMyBaseObjectList уже заставляет T иметь тип TMyBaseObject. Если вы объявите класс T: в TMyObjectList, он не будет удовлетворять требованию TMyBaseObjectList.

0 голосов
/ 06 августа 2010

В качестве альтернативы, вы можете уменьшить класс списка с TCollection, а элементы с TCollectionItem и использовать их в качестве базовых классов.Они построены со всей этой сантехникой уже.Чтобы использовать ваш пример:

type
    TTypeA = class(TCollectionItem);

procedure Test;
var
    MyList: TCollection;
    NewListObject: TTypeA;

begin
    MyList := TCollection.Create(TTypeA);
    NewListObject := MyList.Add;
end;

Редактировать: я знаю, что он не использует Generics, но вы можете обратиться к TCollection и TCollectionItem за дополнительными идеями дизайна, особенно когда речь идет о владении, уведомлениях и сроке службыуправление.

0 голосов
/ 06 августа 2010

Я думаю, что это невозможно. Если, конечно, у вас нет предметов в списке, в этом случае вы можете сделать:

  NewListObject := MyList[0].ClassType.NewInstance as TTypeA;
0 голосов
/ 06 августа 2010

В xxx поместите это: TTypeA.Create(...);, где ... - параметры вашего конструктора создания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...