Форум: "Основная";
Текущий архив: 2004.02.02;
Скачать: [xml.tar.bz2];
ВнизСоздать переменную текущего класса. Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.011 c