Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Generics в Delphi XE2 
:(
    Опции темы
omickron
Дата 28.12.2012, 16:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 12.2.2009

Репутация: нет
Всего: 1



Пытаюсь разобраться с дженериками в Delphi XE2.

Не понимаю, чем отличается 
TMyClass<T> = class(TObject)
от
TMyClass<T: class> = class(TObject)

Хочу сделать следующее:

Код

TFactory<?> = class(TObject)
private
  FList: TDictionary<stirng, T>;
public
  function GetInstance: TMyClass<T>
  //Добавляет тип в словарь
  class procedure RegisterType(AType: T); 
  //Создаёт объект хранимого типа и возвращает его.
  function CreateTypeInstance(AType: string): T;

function TFactory<?>.CreateTypeInstance(AType: string): T;
begin
  Result := FList[AType].Create;
end;



Порядок использования:
Код

TMyFactory = class(TFactory<TMyClass>)
end;

//В коде:
TMyClass1 = class(TMyClass);
TMyClass2 = class(TMyClass);
TMyFactory.RegisterType(TMyClass1);
TMyFactory.RegisterType(TMyClass2);

var Value: TMyClass;
Value := TMyFactory.GetInstance.CreateTypeInstance('TMyClass1');
try
 //Используем Value
finally
  Value.Free;
end;


Суть в том, чтобы перед началом работы зарегистрировать в фабрике всех наследников TMyClass, а потом создавать их, зная только имя.
Но не пойму, чем отличается TMyClass<T> от TMyClass<T: class>
Если использовать второй вариант, то ругается здесь:
TMyFactory.RegisterType(TMyClass1); //[DCC Error] Incompatible types: 'TMyClass' and 'class of TMyClass1'
Т.е. хочет, чтоб я передал TMyClass1.Create. А я не хочу создавать объект сейчас. Я хочу просто зарегистрировать тип.
Как нужно описать тип TFactory?
PM MAIL   Вверх
Illusion Dolphin
Дата 28.12.2012, 18:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

Не понимаю, чем отличается 
TMyClass<T> = class(TObject)
от
TMyClass<T: class> = class(TObject)

В первом случае T - любой тип, во втором T должен быть классом.

TFactory<TMyClass> - значит что T это объекты типа TMyClass. Чтобы туда добавлять типы объектов, надо сделать:
Код

type
  TMyClassType = class of TMyClass;

TMyFactory = class(TFactory<TMyClassType>)
end;



--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
bems
Дата 28.12.2012, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 31
Всего: 88



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


--------------------
Обижено школьников: 8
PM MAIL   Вверх
omickron
Дата 29.12.2012, 23:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 12.2.2009

Репутация: нет
Всего: 1



bems, Вы совершенно правы. У меня уже есть функционал, который работает, но приходится делать приведение типов.
Я перешёл на XE2 и хочу переписать это с использованием дженериков. Если это, конечно, возможно

Illusion Dolphin, скажите, а что означает такая конструкция:
TMyClass<T: constructor> = class(TObject)
Если я правильно понимаю, означает ли это, что тип, передаваемый в T, должен иметь конструктор без параметров? И тогда можно будет в коде написать что-то вроде Result := T.Create; ?
Как бы указать в параметризации, что я хочу параметризовать класс не объектом, а его типом: не TMyClass, а class of TMyClass.
Если я укажу TFactory<T: class>, это будет означать, что я должен параметризовать его типом TMyClass. А мне нужно параметризовать его типом class of TMyClass.

Это сообщение отредактировал(а) omickron - 29.12.2012, 23:47
PM MAIL   Вверх
Illusion Dolphin
Дата 30.12.2012, 10:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Цитата

Если я правильно понимаю, означает ли это, что тип, передаваемый в T, должен иметь конструктор без параметров? И тогда можно будет в коде написать что-то вроде Result := T.Create; ?

Точно так:

Код

  public
    { Public declarations }
    function CreateClass<T: constructor>: T;


function TForm28.CreateClass<T>: T;
begin
  Result := T.Create;
end;


Вот пример реализации того что в первом посте:
Код

unit Unit28;

interface

uses
  Generics.Collections,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TMyClass = class
  end;

  TMyClassType = class of TMyClass;

  TMyClassA = class(TMyClass)
  end;

  TMyClassB = class(TMyClass)
  end;

  TMyClassFactory = class
  private
    FList: TDictionary<string, TMyClassType>;
  public
    constructor Create;
    destructor Destroy; override;
    procedure RegisterClass(ClassType: TMyClassType);
    function CreateInstance(Name: string): TMyClass;
  end;

  TForm28 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form28: TForm28;

implementation

{$R *.dfm}

procedure TForm28.FormCreate(Sender: TObject);
var
  Factory: TMyClassFactory;
  C: TMyClass;
begin
  Factory := TMyClassFactory.Create;
  try
    Factory.RegisterClass(TMyClassA);
    Factory.RegisterClass(TMyClassB);

    C := Factory.CreateInstance('TMyClassB');
    ShowMessage(C.ClassName);
    C.Free;
  finally
    Factory.Free;
  end;
end;

{ TMyClassFactory }

constructor TMyClassFactory.Create;
begin
  FList := TDictionary<string, TMyClassType>.Create;
end;

function TMyClassFactory.CreateInstance(Name: string): TMyClass;
begin
  Result := FList[Name].Create;
end;

destructor TMyClassFactory.Destroy;
begin
  FList.Free;
  inherited;
end;

procedure TMyClassFactory.RegisterClass(ClassType: TMyClassType);
begin
  FList.Add(ClassType.ClassName, ClassType);
end;

end.



P.S. Практического смысла тут не вижу.



--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
omickron
Дата 30.12.2012, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 12.2.2009

Репутация: нет
Всего: 1



Illusion Dolphin, смысл в том, чтобы сделать общую фабрику, которая будет оперировать типами классов (class of TMyClass). TFactory<T> = class(TObject).
А потом TMyClassType = class of TMyClass и TMyFactory = class(TFactory<TMyClassType>). И TMyFactory будет отдавать зарегистрированные типы по имени.

Вот есть общая фабрика TFactory<T> и у неё есть метод GetElement(Name: string): T;
и её наследник: TMyClassFactory = class(TFactory<TMyClass>)
Что будет возвращать GetElement? TMyClass или TMyClass.Create? Созданный объект или тип объекта?

* Если указать TFactory<T>, T - любой тип. 
* Если указать TFactory<T: class>, в T можно передавать только классы.
* Если указать TFactory<T: class, constructor>, в T можно передавать классы, у которых есть конструктор без параметров.
Что во всех этих случаях будет возвращать GetElement: T? 

И что нужно указать вместе с T, чтобы передавать не TMyClass, а TMyClassType?
PM MAIL   Вверх
Illusion Dolphin
Дата 30.12.2012, 11:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



при:
Цитата

Вот есть общая фабрика TFactory<T> и у неё есть метод GetElement(Name: string): T;
и её наследник: TMyClassFactory = class(TFactory<TMyClass>)
Что будет возвращать GetElement? TMyClass или TMyClass.Create? Созданный объект или тип объекта?

GetElement возвращает объекты типа TMyClass (т.е. созданные объекты)

Цитата

И что нужно указать вместе с T, чтобы передавать не TMyClass, а TMyClassType? 

Код

 TMyClassFactory = class(TFactory<TMyClassType>)

? Я не понимаю, в чём проблема. 


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
omickron
Дата 30.12.2012, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 12.2.2009

Репутация: нет
Всего: 1



Код

TMyClassFactory = class(TFactory<TMyClassType>)

А как объявить TFactory<?>, чтоб эта общая фабрика знала, что она будет параметризована типом объекта? Например, чтоб можно было сделать такой метод:
Код

procedure TFactory<?>.RegisterClass(AClass: T);
begin
  FList.Add(T.ClassName, T); //Здесь FList - словарь из примера выше.
end;


Осталось понять только это smile
PM MAIL   Вверх
Illusion Dolphin
Дата 30.12.2012, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 36
Всего: 63



Если я правильно понял, то тут RTTI надо:
Код

unit Unit28;

interface

uses
  Generics.Collections,
  System.TypInfo,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TMyClass = class
  end;

  TMyClassA = class(TMyClass)
  end;

  TMyClassB = class(TMyClass)
  end;

  TMyClassFactory<T: class, constructor> = class
  private
    FList: TDictionary<string, TClass>;
  public
    constructor Create;
    destructor Destroy; override;
    procedure RegisterClass<T>();
    function CreateInstance(Name: string): T;
  end;

  TForm28 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form28: TForm28;

implementation

{$R *.dfm}

procedure TForm28.FormCreate(Sender: TObject);
var
  Factory: TMyClassFactory<TMyClass>;
  C: TMyClass;
begin
  Factory := TMyClassFactory<TMyClass>.Create;
  try
    Factory.RegisterClass<TMyClassA>();
    Factory.RegisterClass<TMyClassB>();

    C := Factory.CreateInstance('TMyClassB');
    ShowMessage(C.ClassName);
    C.Free;
  finally
    Factory.Free;
  end;
end;

{ TMyClassFactory<T> }

constructor TMyClassFactory<T>.Create;
begin
  FList := TDictionary<string, TClass>.Create;
end;

function TMyClassFactory<T>.CreateInstance(Name: string): T;
begin
  Result := T(FList[Name].Create);
end;

destructor TMyClassFactory<T>.Destroy;
begin
  FList.Free;
  inherited;
end;

procedure TMyClassFactory<T>.RegisterClass<T>;
var
  TI: PTypeInfo;
begin
  TI := PTypeInfo(TypeInfo(T));
  FList.Add(TI.Name, GetTypeData(TI).ClassType);
end;

end.


P.S. Сделал хранилище типом TDictionary<string, TClass>

Это сообщение отредактировал(а) Illusion Dolphin - 30.12.2012, 11:49


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
omickron
Дата 30.12.2012, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 97
Регистрация: 12.2.2009

Репутация: нет
Всего: 1



Ага. Спасибо. Изучу этот аспект. Возможно, то, что надо smile
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

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

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0813 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.