Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2013.06.02;
Скачать: CL | DM;

Вниз

Создать определенный класс.   Найти похожие ветки 

 
vxxv   (2013-01-21 14:44) [0]

Допустим есть базовый класс: BaseClass.
От него наследуются Class_1, Class_2... и т.д.
Допустим нужно сейчас создать Class_2.
Как определить, что именно этот класс нужно создавать?

Так:


function CreateClass(Type_: Integer): BaseClass;
begin
  case Type_ of
     TYPE_CLASS_1: Result:= Class_1.Create;
     TYPE_CLASS_2: Result:= Class_2.Create;
 
     ...
  end;
end;



Или как?


 
Ega23 ©   (2013-01-21 14:59) [1]

TSomeClass = class
public
 constructor Create; virtual;
end;

TClassOfSomeClass = class of TSomeClass;

TSecondClass = class (TSomeClass);

TThirdClass = class (TSomeClass);

function CreateClass(aClassType: TClassOfSomeClass): TSomeClass;
begin
 Result := aClassType.Create;
end;

CreateClass(TSomeClass);
CreateClass(TSecondClass);
CreateClass(TThirdClass);


 
TUser ©   (2013-01-21 15:35) [2]

Я бы мелкую прожку написал, которая генерит нечто вроде

{                                                    }
{ This file is autogenerated by GenerateCode program }
{                                                    }

function CreateElementByName (const Name: string): TSimpleElement;
begin
 if Name = "" then
   result := TSimpleElement.Create
   else

 if Name = "map" then
   result := TMapElement.Create
   else
 if Name = "map_all" then
   result := TMapElementLst.Create
   else

 if Name = "sht" then
   result := TSheetElement.Create
   else
 if Name = "sht_all" then
   result := TSheetElementLst.Create
   else

 if Name = "reg" then
   result := TRegion.Create
   else
 if Name = "reg_all" then
   result := TRegionLst.Create
   else

 if Name = "hel" then
   result := THelixElement.Create
   else
 if Name = "hel_all" then
   result := THelixElementLst.Create
   else

{%all off}{%proton on printscript on}
 if Name = "unit" then
   result := TArchUnitElement.Create
   else
 if Name = "unit_all" then
   result := TArchUnitElementLst.Create
   else
{%all on}

....

потому что переносимость - FreePascal под Linux это читает и ему хорошо. А как он с RTTI совместим у меня не было желания выяснять. Чем проще, тем универсальнее.


 
Dimka Maslov ©   (2013-01-21 21:57) [3]

type
 TSomeClass = class
 public
   constructor Create; virtual;
 end;

 TClassOfSomeClass = class of TSomeClass;

 TSecondClass = class (TSomeClass);

 TThirdClass = class (TSomeClass);

const
 Classes: array[1..3] of TClassOfSomeClass = (TSomeClass, TSecondClass,
   TThirdClass);

function CreateClass(Index: Integer): TSomeClass;
begin
 if (Index >= Low(Classes)) and (Index <= High(Classes)) then
   Result := Classes[Index].Create
 else
   Result := nil;
end;


 
Kerk ©   (2013-01-21 23:22) [4]

Конкурс у кого фантазия богаче? :)


 
uw ©   (2013-01-22 00:29) [5]

Dimka Maslov ©   (21.01.13 21:57) [3]

Тогда уж так:

type
TSomeClass = class
public
  constructor Create; virtual;
end;

TClassOfSomeClass = class of TSomeClass;

TSecondClass = class (TSomeClass);

TThirdClass = class (TSomeClass);

const
Classes: array[1..3] of TClassOfSomeClass = (TSomeClass, TSecondClass,
  TThirdClass);

function TForm1.FormCreate(Sender: TObject);
var
 SomeVar: TSomeClass;
begin
 SomeVar := Classes[2].Create;
 SomeVar.Free;
end;

end.


 
uw ©   (2013-01-22 00:37) [6]

Я хотел написать:

function CreateClass(Index: Integer): TClassOfSomeClass;
begin
 Result := Classes[Index];
end;

function TForm1.FormCreate(Sender: TObject);
var
SomeVar: TSomeClass;
begin
SomeVar := CreateClass(2).Create;
SomeVar.Free;
end;


 
Dimka Maslov ©   (2013-01-22 10:11) [7]


> uw ©   (22.01.13 00:37) [6]


Дополнительная проверка на нахождение индекса в диапазоне и последующая проверка указателя на объект, а не на метакласс не помешает.


 
uw ©   (2013-01-22 10:43) [8]

Да ведь по-любому всё будет охвачено оператором try, а автор хочет, чтобы ему создали класс, а не экземпляр :)


 
Dimka Maslov ©   (2013-01-22 13:13) [9]


> uw ©   (22.01.13 10:43) [8]


Автор путает понятия «класс» и «объект», но судя по коду ему надо таки объект определённого класса, на этапе компияции неизвестного.


 
uw ©   (2013-01-22 15:32) [10]

То, что автор путает, это понятно. Но из нашего обсуждения напрашиваются два вопроса:

1. А надо ли в Delphi делать дополнительные проверки, если синтаксис позволяет определять ограниченные типы вроде TType = 1..3, включать соответствующие опции компилятора и пользоваться механизмом исключений?

2. А есть ли смысл пользоваться функциями, возвращающими метаклассы, как я это предложил выше? Я, например, воспользовался этим всего-то один раз, и то можно было возвращать экземпляр. Но ведь так круто!


 
Дмитрий С ©   (2013-01-22 16:14) [11]


> Автор путает понятия «класс» и «объект»,

Тогда уж "экземпляр класса", а не "объект".


 
icWasya ©   (2013-01-22 16:15) [12]

Варианты, предлагаемые в [2],[3],5] и автором, предполагают, что список классов не меняется, или при каждом таком изменении надо будет переписывать функцию CreateClass. Если это не напрягает - то флаг в руку.
Подход применяемый в Дельфи заключается в том, что функция CreateClass и обвязка вокруг неё пишется один раз в отдельном модуле, который знать не знает, объекты каких классов будут создаваться. А модули, в которых находятся объявления классов, только регистрируют свои классы для использования в этой системе.


 
Ega23 ©   (2013-01-22 16:24) [13]


> Подход применяемый в Дельфи заключается в том, что функция
> CreateClass и обвязка вокруг неё пишется один раз в отдельном
> модуле, который знать не знает, объекты каких классов будут
> создаваться. А модули, в которых находятся объявления классов,
>  только регистрируют свои классы для использования в этой
> системе

Можно и без регистрации, см. [1]


 
Dimka Maslov ©   (2013-01-22 16:39) [14]


> uw ©   (22.01.13 15:32) [10]


1. Даже в ограниченный тип при желании можно неправильный индекс, который никакой проверкой не проверится. К тому же, лучше получить исключение в прогнозируемом месте, а не ждать, когда неправильный адрес уйдёт неизвестно куда.

2. Тип, возвращаемый функцией, метакласс или готовый объект сильно зависит от поставленной задачи. К тому же для метаклассов неприменимы операторы is и as, и если нам захочется проверить, что вернула функция, нам всё равно придётся создавать объект. А для данного примера это вообще непринципиально.


 
uw ©   (2013-01-22 18:05) [15]

1. Даже в ограниченный тип при желании можно неправильный индекс, который никакой проверкой не проверится.

Даёт исключение, если включить Check Range.


 
Dimka Maslov ©   (2013-01-22 18:19) [16]


> uw ©   (22.01.13 18:05) [15]


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


 
uw ©   (2013-01-22 19:56) [17]

Интересное желание. Приведи, пожалуйста, пример, как ты это будешь делать.


 
Dimka Maslov ©   (2013-01-22 21:05) [18]

type
 PClassArray = ^TClassArray
 TClassArray = array[1..3] of TClass;

 PClassArrayEx = ^TClassArrayEx;
 TClassArrayEx = array[1..100] of TClass;

var
 T: TClassArray;
 P: PClassArrayEx;

 P := PClassArrayEx(Pointer(@T));

 P^[4].Create;


 
uw ©   (2013-01-22 21:51) [19]

Ну что ж, теперь я понял, зачем ты делаешь дополнительные проверки :)



Страницы: 1 вся ветка

Текущий архив: 2013.06.02;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.008 c
15-1358364990
zzz
2013-01-16 23:36
2013.06.02
Посоветуйте принтер


15-1359311215
Jimmy
2013-01-27 22:26
2013.06.02
Оценочные функции игр на доске


15-1358278949
masha
2013-01-15 23:42
2013.06.02
беговые лыжи


15-1359516511
Кто б сомневался
2013-01-30 07:28
2013.06.02
Как запускать игру)


15-1359232203
Юрий
2013-01-27 00:30
2013.06.02
С днем рождения ! 27 января 2013 воскресенье