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

Вниз

Создать переменную текущего класса.   Найти похожие ветки 

 
tria ©   (2004-01-21 14:29) [0]

Вопрос в следующем. Есть иерархия:
TBaseClass=Class;
TClass1=Class(TBaseClass);
TClass2=Class(TBaseClass1);
TClass11=Class(TBaseClass);

Есть процедура, в кот. передается переменная класса:
procedure Proc1(p:TBaseClass);
var p1:TBaseClass;
begin
p1:=TBaseClass.Create;
... и чего то там еще...
end;

Переменная p может быть любого из вышеприведенных типов (TClass1,TClass2,TClass11).
Задача: создать p1 того же типа, что и фактически переданный параметр.


 
Skier ©   (2004-01-21 14:32) [1]

метакласс используй.


 
Тимохов ©   (2004-01-21 14:33) [2]

p.ClassType.Create;


 
tria ©   (2004-01-21 14:34) [3]

Честно говоря, не знаю что это такое.


 
Тимохов ©   (2004-01-21 14:34) [4]

Правда, еще зависит от того как у тебя выглядит Create.


 
tria ©   (2004-01-21 14:36) [5]

Спасибо, Тимохов.


 
Тимохов ©   (2004-01-21 14:36) [6]


> Честно говоря, не знаю что это такое.

Если ты про [2], то воспользуйся F1.


 
Тимохов ©   (2004-01-21 14:48) [7]

Автору
Обрати внимание на Тимохов © (21.01.04 14:34) [4].
Если ты собираешься делать в каждом классе свой конструктор Create, то делай в базовом классе его virtual, а в потомках override.

И вообще я немного не прав:
писать надо так TBaseClasses(p.ClassType).Create, где TBaseClasses = class of TBaseClass. Иначе будет вызваться Create у TObject, а твой create вообще не будет вызываться.


 
pasha_golub ©   (2004-01-21 15:02) [8]

2Тимохов
В принципе про это Skier и говорил.


 
Тимохов ©   (2004-01-21 15:04) [9]

pasha_golub © (21.01.04 15:02) [8]
Просто у скаера были очень умные слова, которые не всем понятны (даже мне :))))
Полагаю, что он это и имел в виду.


 
pasha_golub ©   (2004-01-21 15:21) [10]

2Тимохов © (21.01.04 15:04) [9]
Эт точно. :-) На то он и Мастер.


 
Юрий Зотов ©   (2004-01-21 16:29) [11]

> tria © (21.01.04 14:29)

А если без умных слов, и поконкретнее, то так.

type
TBaseClass = class
...
constructor Create(...); virual;
...
end;

TClassOfBaseClass = class of TBaseClass;

TClass1 = class(TBaseClass)
...
end;

TClass2 = class(TBaseClass1)
...
end;

и т.д.

procedure Proc1( RealBaseClass: TClassOfBaseClass);
var
p1: TBaseClass;
begin
p1 := RealBaseClass.Create(...);
...
end;


 
Тимохов ©   (2004-01-21 16:34) [12]

Юрий Зотов © (21.01.04 16:29) [11]

1. Ему надо не procedure Proc1(RealBaseClass: TClassOfBaseClass), а procedure Proc1(RealBaseClass: TBaseClass), что согласитель разные вещи.
2. Про конструктор он вообще ничего не сказал - может ему штатного TOBject.Create хватит, тогда не надо virtual


 
Юрий Зотов ©   (2004-01-21 16:45) [13]

> Тимохов © (21.01.04 16:34) [12]

> что согласитель разные вещи.

Разные. Но ClassType еще не отменили. И я полагаю, что решение задачи о поимке ручного льва в пустыне Сахара должно нами рассматриваться так же, как и в той книжке, где эта задача была впервые сформулирована.

> 2. Про конструктор он вообще ничего не сказал - может ему
> штатного TOBject.Create хватит, тогда не надо virtual

А вот здесь Вы, IMVHO, очень сильно и очень принципиально ошибаетесь. При статическом конструкторе будет всегда создаваться объект одного и того же класса - того, который объявлен в самой процедуре. TBaseClass, в общем.


 
Тимохов ©   (2004-01-21 17:03) [14]


> А вот здесь Вы, IMVHO, очень сильно и очень принципиально
> ошибаетесь. При статическом конструкторе будет всегда создаваться
> объект одного и того же класса - того, который объявлен
> в самой процедуре. TBaseClass, в общем.


Может проверим?

type
tcc1 = class of tc1;
tc1 = class(tobject)
procedure show; virtual;
end;
tc2 = class(tc1)
procedure show; override;
end;

procedure tc1.show;
begin
showmessage("


 
Тимохов ©   (2004-01-21 17:05) [15]


> > Тимохов © (21.01.04 16:34) [12]
>
> > что согласитель разные вещи.
>
> Разные. Но ClassType еще не отменили. И я полагаю, что решение
> задачи о поимке ручного льва в пустыне Сахара должно нами
> рассматриваться так же, как и в той книжке, где эта задача
> была впервые сформулирована.


С этим тоже сложно согласиться. Задача в том, что есть объект надо сделать его клон того же класса.

Все правы, но автор спрашивал другое.


 
Тимохов ©   (2004-01-21 17:21) [16]

Юрий Зотов!
Откликнитесь на [14]. Может я что-то не так понимаю? Мне чессослово интересно...


 
Юрий Зотов ©   (2004-01-21 17:29) [17]

> Тимохов © (21.01.04 17:21) [16]

А чего тут не понимать? Зависит от реализации. Если использовать метакласс - то да, а если нет - то при статическом конструкторе всегда будет создаваться один и тот же класс.


 
Тимохов ©   (2004-01-21 17:38) [18]

Что-то не очень понятно.

В 14 был приведен пример, который вроде как противоречит вашему возражению из 13 на мою фразу "Про конструктор он вообще ничего не сказал - может ему штатного TOBject.Create хватит, тогда не надо virtual". Вы сказали, что я принципиально ошибаюсь, может все-таки не принципиально и не ошибаюсь вовсе? :)))

По сему автору вопроса в реализации, предложенной в одном из первых ответов, не обязательно делать virtual для конструкторов.

Да вобщем-то и в Вашем примере из 11 не обязательно делать virtual - будет работать правильно и без этого.


 
Skier ©   (2004-01-21 17:40) [19]

>Тимохов © (21.01.04 17:38) [18]
А ты проверь без virtual ...через ClassName...


 
Тимохов ©   (2004-01-21 17:44) [20]

Skier © (21.01.04 17:40) [19]
Все работает

Я прорюхал про что речь и в чем наше непонимание.
Если в каждом классе потомке BaseClass нужен свой конструктор, то нужно писать в TBaseClass.crate; virtual; Если же все потомки могут обойтить конструктором TBaseClass.crate, то virtual не нужен.


 
Тимохов ©   (2004-01-21 17:45) [21]

Т.о. все зависит от исходной задачи...


 
Skier ©   (2004-01-21 17:48) [22]


> Т.о. все зависит от исходной задачи...

всё зависит от того что попадёт в ссылку на класс.


 
Тимохов ©   (2004-01-21 17:49) [23]


> всё зависит от того что попадёт в ссылку на класс.

Замечание не понято :(((


 
Skier ©   (2004-01-21 17:50) [24]


> Замечание не понято :(((

А жаль...


 
Тимохов ©   (2004-01-21 17:52) [25]

Skier © (21.01.04 17:50) [24]
Это уже наезд... :(((
Во всем, что я сказал я, к сожалению для некоторых, прав.


 
tria ©   (2004-01-21 18:18) [26]

>Skier
А можно замечание повторить поподробней? А то мне с этим жить, и уж больно хочется разобраться?


 
tria ©   (2004-01-21 18:24) [27]

Пример, который привел Тимохов работает, ClassName возвращает tc2. Подводных камней, к сожалению, не вижу.
Конструктор у меня пока один на все классы, но в дальнейшем может и будут разные. Проверил - вызывается конструктор нужного класса.


 
Тимохов ©   (2004-01-21 18:26) [28]

tria © (21.01.04 18:24) [27]
Если у тебя может быть потребность в разных конструкторах (т.е. в потомке нужен свой конструктор) то слушайся Юрия Зотовова. Приши в TBaseClass constructor Create; virtual и создавай объекты так TBaseClasses(p.ClassType).Create.


 
tria ©   (2004-01-21 18:30) [29]

Тимохов
Я понял.
Проверил - это взял Ваш код, добавил конструктор с директивой virtual, перекрыл в наследнике. При создании вызвался конструктор класса tc2. Так что на мой взгляд Ваш код рабочий.


 
Тимохов ©   (2004-01-21 18:38) [30]

Все мысли высказанные тут рабочие - все зависит от Вашей потребности.

С методологической точки зрения самый правый (в смысле правильный) это Юрий Зотов - всегда пишите у конструктора virtual и всегда все будет ОК.


 
Тимохов ©   (2004-01-21 18:55) [31]


> Проверил - это взял Ваш код, добавил конструктор с директивой
> virtual, перекрыл в наследнике. При создании вызвался конструктор
> класса tc2. Так что на мой взгляд Ваш код рабочий.

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

В качестве примера можете это посмотреть

type
tcc1 = class of tc1;
tc1 = class(tobject)
constructor create();
end;
tc2 = class(tc1)
constructor create();
end;

constructor tc1.create();
begin
showmessage("tc1 constructor, class name = "+classname);
end;

constructor tc2.create();
begin
showmessage("tc2 constructor, class name = "+classname);
end;

procedure p(o: tcc1);
var
oo: tc1;
begin
oo := o.create();
end;

procedure TForm1.Button10Click(Sender: TObject);
begin
p(tc1); // создается класс Tc1 вызывается констр. tc1.create.
p(tc2); // создается класс Tc2 вызывается констр. tc1.create.
end;

Вообще хочу вернуться к совету слушать Юрия Зотова. Повторюсь, что с точки зрения методики написания программ он более прав.


 
tria ©   (2004-01-21 19:07) [32]

Собственно говоря, последний пример - наиболее простое решение задачи ...


 
Тимохов ©   (2004-01-21 19:13) [33]


> Собственно говоря, последний пример - наиболее простое решение
> задачи ...

Вы имели в виду пример из [31]?
Все-таки лучеше пишите virtual :))) Спокойнее будет жизнь...


 
tria ©   (2004-01-21 19:19) [34]

Ладно уж стебаться...
Подведу для себя итог: всей глубины вопроса я так и не осознал, но как решить мою задачу и к каким последствиям может привести то или иное решение понял.
Всем еще раз спасибо, убегаю на очень приятное занятие - играть в футбол.



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

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

Наверх




Память: 0.55 MB
Время: 0.017 c
14-2307
Юрий Федоров
2004-01-07 22:16
2004.02.02
Нужно снять квартиру в Москве


14-2292
Senator
2004-01-12 16:29
2004.02.02
фича


3-2036
СлБ
2004-01-06 08:12
2004.02.02
QuickReport программно сохранить/открыть отчет


3-2042
SnapIn
2004-01-05 05:14
2004.02.02
Работа с FoxPro (поиск по полю типа Date)


4-2416
Les
2003-11-25 11:01
2004.02.02
Чтение файла шрифта