Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
14-2341
Труп Васи Доброго
2004-01-10 08:59
2004.02.02
Мародёры!!! Ник украли!!! Маздай полный!!!


1-2207
Alexis
2004-01-20 20:47
2004.02.02
приложение без формы...


1-2231
man
2004-01-19 19:49
2004.02.02
как получить список процессов, которые используют данный файл


14-2301
Layner
2004-01-12 13:05
2004.02.02
Приветствую всех! Поделитесь, у кого есть форма договора на


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





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский