Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2003.09.08;
Скачать: [xml.tar.bz2];

Вниз

Класс-оболочка в каждой форме, исходный - один в главной   Найти похожие ветки 

 
Dm1625   (2003-08-25 13:18) [0]

не могу сообразить как это написать правильно

в главной форме проекта создается класс - один экземпляр
все формы проекта вызывают функции этого экземпляра

надо: обернуть этот класс, чтобы формы вызывали функции класса-оболочки (один экземпляр класса-оболочки в каждой форме), ну а функции класса-оболочки будут добавлять идентификатор формы и вызывать уже настоящую функцию

что-то вроде
TClass = class
function F1(FormID: longint)
end;

TClassWrapper = class
function F1 () - вызывает function F1(FormID: longint)
и подставляет идентификатор формы, который получает при создании
end;

FrmMain
Class1: TClass;
end;

FrmAny
ClassWrapper1: TClassWrapper;

и надо правильно конструкторы оформить


 
unreger   (2003-08-25 13:39) [1]

Это я был

Поясню: класс работает с данными, один экземпляр
чтобы все формы обмениваются данными с сервером через него (меняются только параметры и хранимые процедуры, механизм один),
чтобы не писать обработчик ошибок в каждой форме, поместим обработчик в класс. Но надо знать какая форма вызвала функцию. Эту задачу выполняет класс-оболочка, экземпляр которого есть в каждой форме.


 
Skier   (2003-08-25 13:42) [2]

Если я правильно понял то видимо так :

TClass = class
function F1(FormID: longint); virtual;
end;

TClassWrapper = class
function F1(FormID: longint); override;
end;

Нет ?


 
Palladin   (2003-08-25 13:42) [3]

TClass = class
function F1(FormID: longint); virtual;
end;

TClassWrapper = class (TClass)
function F1; override;
end;

function TClassWrapper.F1;
begin
inherited (1);
end;


 
unreger   (2003-08-25 13:48) [4]

э-э-э...

По моему не так.

TClass совершенно реальный, создается один экземпляр этого класса, в нем код, который выполняется

TClassWrapper просто вызывает функцию из экземпляра TClass (но экземпляр TClassWrapper в каждой форме)

примерно так

TClassWrapper.F1()
begin
TClass.F1(FormID); FormID получен при создании TClassWrapper
end;

Я вызываю F1(), а оболочка подставляет параметры и вызывает дальше.


 
Palladin   (2003-08-25 13:51) [5]

Экземпляр класса называется объект, в вопросе шла именно речь о наследовании классов.


 
Skier   (2003-08-25 13:53) [6]

Поправлюсь : TClassWrapper = class(TClass) конечно же...


 
Palladin   (2003-08-25 13:53) [7]

И что значит фраза "TClass совершенно реальный"? Skier и я что то не реальное привели чтоли?


 
Skier   (2003-08-25 13:55) [8]

Да и хорошо бы класс не называть TClass, такой в Delphi уже имеется...


 
unreger   (2003-08-25 14:11) [9]

>Экземпляр класса называется объект, в вопросе шла именно речь о наследовании классов.

согласен, с терминологией я был неправ.
Попробуем еще раз:

В главной форме проекта создается экземпляр класса.
CData: TCData;
Этот экземпляр единственный для всего проекта.

В каждой форме создается экземпляр класса-оболочки.
CDataWrapper: TCDataWrapper;

CDataWrapper при создании получает (как?) ссылку на CData и идентификатор формы, в которой создается.

Набор функций CDataWrapper полностью дублирует CData, но
с уменьшеным количество параметров

CDataWrapper.F1()
begin
// вот тут надо решить через указатель на CData
CData.F1(FormID); FormID получен при создании CDataWrapper
end;


 
unreger   (2003-08-25 14:14) [10]

>И что значит фраза "TClass совершенно реальный"?
имелось ввиду "не содержит виртуальных функций"


 
Skier   (2003-08-25 14:15) [11]


> Набор функций CDataWrapper полностью дублирует CData, но
> с уменьшеным количество параметров

справук по overload посмотри, кроме того могут помочь
дефолтные параметры.


 
unreger   (2003-08-25 14:23) [12]

почему overload?
мне важно выполнять код из экземпляра CData, не перекрывая, т.е.

CDataWrapper.F1()
begin
inherited F1(FormID);
end;

пожалуй не пойдет

я представляю что-то вроде
constructor TCDataWrapper.Create(GeneralData: ^TCData) - что-то вроде этого
и определяем класс формы, в котором создали CDataWrapper


 
Palladin   (2003-08-25 14:26) [13]

хм, все это мне напоминает паттерны mediator и command...
почитай на rsdn статью в разделе "паттерны проектирования" там про это рассказано, и не только про это. Причем построено реальное приложение.


 
Camus   (2003-08-25 14:27) [14]

А зачем вообще какие-то оболочки?

type
TCData = class(...)
...
procedure MyProc(Form: TForm; ...);
end;

TForm1 = class(TForm)
...
private
FCData: TCData;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property CData: TCData read FCData;
end;

constructor TForm1.Create(AOwner: TComponent);
begin
inherited;
FCData := TCData.Create(...)
end;

destructor TForm1.Destroy;
begin
FCData.Free;
inherited
end;

И все. Вызов из любой формы, например, такой:
Form1.CData.MyProc(Self, ...);
(естественно, модуль с TForm1 надо включить в uses).


 
Skier   (2003-08-25 14:27) [15]


> CDataWrapper.F1()
> begin
> inherited F1(FormID);
> end;
>
> пожалуй не пойдет

Почему ? Доводы...


 
unreger   (2003-08-25 14:28) [16]

обязательно, но с указателями помоги сейчас?
А я дальше расскажу интересную идею.


 
Palladin   (2003-08-25 14:29) [17]

а указатель тебе зачем? прямо так передавай.


 
unreger   (2003-08-25 14:29) [18]

>Form1.CData.MyProc(Self, ...);
Вот это-то и не хочется. За счет оболочки будет так:
Form1.CData.MyProc(...);


 
unreger   (2003-08-25 14:32) [19]

>а указатель тебе зачем? прямо так передавай.

и что будет? В смысле - останется ли один экземпляр CData? Или будет создан еще один внутри экземпляра CDataWrapper ?


 
Skier   (2003-08-25 14:33) [20]


> Или будет создан еще один внутри экземпляра CDataWrapper
> ?

А почему он должен создаваться ?!
Ты всех уже запутал ! :)
Давай выкладывай проблему целиком !


 
Camus   (2003-08-25 14:36) [21]

> unreger (25.08.03 14:29) [18]
> Вот это-то и не хочется. За счет оболочки будет так:
> Form1.CData.MyProc(...);

То есть, ТОЛЬКО ради того, чтобы не передавать один параметр, плодим кучу дополнительных объектов?
Смысл?


 
unreger   (2003-08-25 14:37) [22]

проблема у меня :)
с указателями.

constructor TCDataWrapper.Create(GeneralData: TCData)

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


 
default   (2003-08-25 14:38) [23]

unreger (25.08.03 14:37) [22]
на копию


 
Skier   (2003-08-25 14:38) [24]


> Вот мне кажется, что будет создан экземпляр класса TCData

Не будет.

> GeneralData: TCData - это же указатель, и передается тоже
> указатель на уже существующий экземпляр, правильно?

Правильно.

Ещё что нужно развеять ? :)


 
unreger   (2003-08-25 14:39) [25]

То есть, ТОЛЬКО ради того, чтобы не передавать один параметр, плодим кучу дополнительных объектов?

А они маааленькие...

Указатель очень часть придется передавать. Буквально в каждой функции проекта.


 
Skier   (2003-08-25 14:39) [26]

>default © (25.08.03 14:38) [23]
???!!!


 
unreger   (2003-08-25 14:40) [27]

default
на копию

Skier
> указатель на уже существующий экземпляр, правильно?
Правильно

Вы уж определитесь


 
Camus   (2003-08-25 14:40) [28]

> Вот мне кажется, что будет создан экземпляр класса TCData?

С какой стати? Передается ссылка (адрес), вот и все. А уж на что там она указывает, верно или неверно, существует по этому адресу объект или не существует - за это отвечает программист.


 
Skier   (2003-08-25 14:42) [29]

>unreger (25.08.03 14:40) [27]


> Вы уж определитесь

А что тут определяться !
Не слушай default и жизнь наладится.


 
default   (2003-08-25 14:42) [30]

Skier © (25.08.03 14:39) [26]
да, указатель на оригинал по-моему(основываясь на практике)
значит если var ставить ничего не изменится..
щас влом в CPU смотреть


 
Camus   (2003-08-25 14:43) [31]

Передается действительно копия (нет var), но копия не объекта, а его адреса. Указывает же она на все тот же объект.


 
Skier   (2003-08-25 14:46) [32]

>default © (25.08.03 14:42) [30]
Не надо про var !
Копируется только указатель, а не объект.
Автора интересует объект !


 
default   (2003-08-25 14:47) [33]

Camus © (25.08.03 14:43) [31]
ещё бы передавался указатель на указатель была бы вообще сказка...
unreger
оригинал оригинал(просто var компилятор не даёт "ставить")


 
unreger   (2003-08-25 14:48) [34]

Ну и ладно, но не поверите, тупо сидел с этой проблемой ... очень долго.

Слушайте дальше, зачем все это.

В проекте используются только функции из CData, других мало и не важны. В CData создается СОЕДИНЕНИЕ с сервером. Для контроля и различения пользователей особо требуем именно одно соединение.

Когда связь пропадет, или на сервере проверка данных не пройдет, возникнет ошибка. Чтобы не оборачивать каждый вызов функции в try-except, я все обработчики помещаю в CData. Вот зачем при вызове функции надо знать из какой формы он пришел.

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


 
default   (2003-08-25 14:50) [35]

вообще изначально вопрос про указатель был туп поскольку
переменная типа объекта это указатель, а они всегда передаются "как есть"
P.S. просто я малость не выспался...


 
unreger   (2003-08-25 14:51) [36]

Ну сбивает меня отсутсвие необходимости явно обозначать указатель


 
Skier   (2003-08-25 14:54) [37]

Ну и ?
Чем наследование не устраивает ? Не понимаю...


 
default   (2003-08-25 14:55) [38]

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


 
unreger   (2003-08-25 14:57) [39]

>Чем наследование не устраивает ? Не понимаю...

Да пожалуй, что и устраивает. Как всегда, пока формулируешь - половину ответа получаешь. Спасибо. Эх бежать надо, но завтра загляну


 
unreger   (2003-08-26 06:25) [40]

Наследование не устраивает тем, что не хочется наследовать поля класса, например, то поле, в котором хранится соединение должно быть одно для всего проекта, а все функции класса используют его.
Для каждого экземпляра TCDataWrapper будет вызываться конструктор предка для инициализации этого поля, что приведет к открытию нового соединения. Нельзя.

Тогда можно, конечно, в CDataWrapper хранить ссылку на это поле, вернее ссылку на объект, туда же, куда ссылается поле базового класса CData. Но это не правильно, поскольку значение поля часто меняется (объект пересоздается) и остлеживать вручную все ссылки...

Получается, мне надо работать именно с экземпляром базового класса, т.е.
constructor TCDataWrapper.Create(GeneralData: TCData)

а к методам будем обращаться так:

function TCDataWrapper.F1(): longint;
begin
F1:=GeneralData.F1(FormID);
end;

Правильно?


 
unreger   (2003-08-26 11:35) [41]

.


 
Skier   (2003-08-26 11:42) [42]


> поле, в котором хранится соединение должно быть одно для
> всего проекта, а все функции класса используют его.

В базовом классе делаешь свойство в котором хранишь соединение, а все
наследники его только используют (можешь сделать его read-only) и в своих
конструкторах не трогают, т.к. оно создаётся только в базовом классе.

Если я всё правильно уловил, то - так...


 
unreger   (2003-08-26 11:50) [43]

>т.к. оно создаётся только в базовом классе.

вот тут я недопонимаю

ссылка на объект "соединение" (TADOConnection) хранится в поле экземпляра класса CData

если я наследую ТCDataWrapper от ТCData, то копируются все поля и методы, т.е. в ТCDataWrapper появляется указатель на объект типа TADOConnection,

но при создании экземпляра CDataWrapper этот указатель еще никуда не указывает. Надо или вызвать конструктор предка или передать ссылку на уже существующий экземпляр CData.

А этого делать не хочется т.к. TADOConnection часто пересоздается.


 
Skier   (2003-08-26 11:56) [44]

Угу. Понял.
Но тогда твой вариант вполне подходит, IMHO.

Только :
TCData.Create; virtual; - конструктор базового класса;
TCDataWrapper.Create(GeneralData: TCData); reintroduce - конструктор класса - потомка;

Не подойдёт ?


 
unreger   (2003-08-26 12:00) [45]

reintroduce

Ой, какие слова ты знаешь... надо посмотреть что такое


 
unreger   (2003-08-26 12:29) [46]

ага, посмотрел, учту на будущее, но:

Класс-потомок, пожалуй, вообще не подойдет как идея.

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

TCDataWrapper ничего не добавляет к функциональности, его едиственное назначение - избавить меня от необходимости вручную передавать идентификатор формы в методы TCData.


 
Skier   (2003-08-26 12:30) [47]


> Класс-потомок, пожалуй, вообще не подойдет как идея.

Ну тогда не создавай его. Что ещё проще...


 
unreger   (2003-08-26 13:31) [48]

да, но это еще надо было понять.

Никто не хочет прокомментировать идею переноса обработчиков ошибок из форм в CData. Т.е. из какой бы формы не вызывались методы CData, я всегда могу вывести MessageBox с родителем-формой, в которой произошла ошибка, но главное, можно будет дописывать уникальные (специфические) способы исправления ошибок для конкретной формы, или пользоваться общим, универсальным.

Хотя вот тут http://delphimaster.net/view/1-1061811424/ немного задумался, похоже не получится проверять наличие метода у формы


 
Skier   (2003-08-26 13:34) [49]


> да, но это еще надо было понять.

В этом-то всё и дело - ты видимо ещё сам не разобрался до конца что
же тебе надо...



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

Форум: "Основная";
Текущий архив: 2003.09.08;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.64 MB
Время: 0.008 c
1-24537
SH
2003-08-26 17:36
2003.09.08
Типы окон и правила их использования


3-24346
Алексей Петухов
2003-08-16 18:33
2003.09.08
Итоги и ApplyUpdate


8-24563
bkv
2003-05-08 17:01
2003.09.08
Проблема в заливке!


4-24740
Danchik
2003-07-08 13:59
2003.09.08
работа с Dll


1-24406
Хишник
2003-08-28 11:14
2003.09.08
Breakpoint не работает? (CBuilder)





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский