Модераторы: Poseidon, Snowy, bems, MetalFan

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Переменные объявление, где объявлять 
:(
    Опции темы
tikitiki
Дата 2.9.2005, 00:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 330
Регистрация: 10.5.2005

Репутация: нет
Всего: нет



Delphi хорошо знаю. Но с переменными не всё ясно.
В Unit переменные можно объявлять в определении
класса формы, наследуемого от TForm, в разделе var и в
определении процедур. Когда переменных в программе много-
это источник потенциальных ошибок.
Как чётче определить, где и какие переменные нужно объявлять?


--------------------
PM   Вверх
Alex
Дата 2.9.2005, 00:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



При хорошем стиле программирования в модулях форм переменных в var части кроме переменной формы быть не должно в обще (если совсем хорошо писать, то и ее быть не должно). Все глобальные переменные объявляйте в private или public части объекта формы в зависимости от того где вы хотите использовать эту переменную.

Многие могут спросить, почему Alex так обозлился на var часть ведь сама среда прописывает переменную формы? Дело в том, что Delphi действительно сама создает глобальную переменную в var части модуля, но у этого метода объявления переменных есть один существенный недостаток. Если вы четко знаете, что в один момент времени экземпляр данной формы может быть только один в приложении, то ничего страшного в таком объявлении переменных нет, но как только возникает ситуация, когда одна и таже форма может быть создана в двух и более экземплярах в один момент времени, то начинаются большие проблемы. Расмотрим мальнький пример: допустим у нас в приложении есть модуль формы, где в var части объявлена переменная "a" типа Integer. При создании формы мы присваиваем этой переменной значение "0" Допустим после создания формы мы в эту переменную с интервалом в одну секунду будем записывать "сколько секунд живет наша форма" и будем выводить это число в label лежащий на этой форме. Если во время работы нашего приложения будет создан один экземпляр формы, то все будет работать, но если вы не закрывая первый экземпляр формы, создадите еще один, то увидите странный на первый взгляд эффект: время жизни на обеих формах будет отображаться одинаковое (хотя первая форма создана была гораздо раньше), отсчет опять начнется с "0" и счетчик каждую секунду будет увеличиваться не на единицу как вам бы хотелось, а уже на два.

Это происходит от того, что переменная объявленная в var части существует в памяти в одном экземпляре, и вы всегда будите ее увеличивать.

еще один недостаток переменных объявленных в var части модуля, что память под них выделяется не при создании объекта формы, а при инициализации модуля (старт программы).

А вот переменные объявленные в private или public части объекта лишены этих недостатков и для правильной работы приведенного выше примера достаточно перенести объявление переменной "a" в private часть объекта формы.

Многие мне сейчас могут сказать: "У меня всегда в приложении может существовать только один экземпляр формы.”
Не зарекайтесь, я тоже когда-то так думал и дорого поплатился в свое время за такие высказывания (в результате пришлось переписывать половину достаточно крупного проекта).

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

В моем текущем проекте 90 форм на весь проект объявлено только одна глобальная переменная "Opt: TIaOption". В этой переменной хранятся настройки приложения, прочитанные из ini файла при старте программы. Все формы в приложении кроме главной могут быть созданы не в одном экземпляре.


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Poseidon
Дата 2.9.2005, 01:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(Alex @ 2.9.2005, 00:47)
Ни в коем случаи не используйте глобальные переменные для передачи данных между формами.

Alex, можно по-подробнее, как поступать в этом случае? Как передавать значение переменных в модуль другой формы не используя глобальных переменных? И чем грозит их использование при передаче данных?


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
Alex
Дата 2.9.2005, 01:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



Приведи пример где ты не видишь другого решения кроме как использование глобальных переменных, а я постараюсь объяснить на твоем примере методы избавлений от глобалов


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Poseidon
Дата 2.9.2005, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



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

Вот например при клике на кнопку у нас появляется диалоговое окно выбора папки (не через компонент). Папку выбрали, что-то с ней сделали (изменили имя допустим). А при клике по другой кнопке нужно эту папку удалить. При этом, для удабства, вызывать повторно диалог выбора папки не рекомендуется, а нужно использовать то, что выбрано при первом клике. Как тут быть?
Я сохраняю путь к папке при первом клике в глобальную переменную, а во втором клике исползую ее.

Это сообщение отредактировал(а) Poseidon - 2.9.2005, 12:29


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
_hunter
Дата 2.9.2005, 13:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 15
Всего: 98



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


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
Alex
Дата 2.9.2005, 14:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



В принцыпе _hunter прав на все 100%, но что-то мне подсказывает, что ты выбранный путь где-то отображаешь и скорей всего это label и если это все так, то и используй этот label как глобальную переменную ведь все равно данные ты в ней отображаешь. Да и память с экономишь, а то получается, что одни и теже данные хранишь два раза в памяти.

PS:
Как видите можно спокой но обходиться без лишних глобальных переменных и на самом деле не так много ситуаций когда без глобаллов нельзя обойтись. По хорошему и в public части не так нужно объявлять переменные


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Alex
Дата 2.9.2005, 14:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



Вот небольшой пример работы с модальными формами.
Проект:
Код

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


Модуль главной формы:
Код

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses
  unit2
;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Label1.Caption:= SelFile(Label1.Caption);
end;

end.


Модуль вызываемой формы:
Код

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm2 = class(TForm)
    Edit1: TEdit;
    Label1: TLabel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

//var
//  Form2: TForm2;

function SelFile(const defFile: String = ''): String;

implementation

{$R *.dfm}

function SelFile(const defFile: String = ''): String;
begin
  with TForm2.Create(Application) do try
    Result:= defFile;
    Edit1.Text:= defFile;
    if ShowModal = mrOk then
      Result:= Edit1.Text;
  finally
    Release;
  end;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  Top:= Top-Height;
  Edit1.Text:= SelFile(Edit1.Text);
end;

end.

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

Использование таких функций создания позволяет вызвать любую форму в любом месте проекта. При этом не важно, сколько экземпляров этой формы у вас уже создано. Так же теперь вы можете одну и туже форму использовать да же в разных проектах. Если вы возьмете себе за правило писать все свои модальные формы в таком стиле, то в дальнейшем не раз скажете себе за это спасибо. Формы, написанные по такой методике идеальны для помещения в dll, если вдруг вы захотите это сделать.


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
Poseidon
Дата 2.9.2005, 15:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Млин, а я думал это единственный вариант!
Alex, _hunter, благадарю! Пошел эксперементировать smile


--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
tikitiki
Дата 2.9.2005, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 330
Регистрация: 10.5.2005

Репутация: нет
Всего: нет



Я чуть с опозданием...

Alex, много стало ясно. Спасибо. А я правильно понял, что в классе формы в
private и public могут не быть переменные, а появиться в аналогичных
разделах при объявлении переменной формы? Нужно ли в такой именно ситуации
избегать переменных в классе формы в private и public?
Ещё плоховатый вопрос. Так я объявляю в переменной формы в public
переменные, а затем для доступа к ним из других модулей в тех модулях
в Uses из Implementation ставлю модуль с объявлениями переменных? Кстати,
я уже запутался, так глобальная переменная доступна становится после
включения в Uses соответствующего Unitа? И ещё кстати, а как же правда
избегать глобальных переменных, если нужно передавать между формами
переменные?что-то таинственное...
Посмотрел Help Delphi-так оказывается всё что не в определении процедуры или
функции -это называется глобальные переменные:т.е. в их число и public
входят(а также private и в интерфейсной Var части и т.д.). Ключевое слово global variables.


--------------------
PM   Вверх
Poseidon
Дата 2.9.2005, 15:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Delphi developer
****


Профиль
Группа: Комодератор
Сообщений: 5273
Регистрация: 4.2.2005
Где: Гомель, Беларусь

Репутация: 53
Всего: 133



Цитата(tikitiki @ 2.9.2005, 15:34)
И ещё кстати, а как же правда
избегать глобальных переменных, если нужно передавать между формами
переменные?что-то таинственное...
Цитата(_hunter @ 2.9.2005, 13:19)
в этом случае ( если используются две формы ) банально объявляется публичная переменная ( в первой форме ) которой присваивается имя и вторая форма его читает




--------------------
Если хочешь, что бы что-то работало - используй написанное, 
если хочешь что-то понять - пиши сам...
PM MAIL ICQ   Вверх
tikitiki
Дата 2.9.2005, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 330
Регистрация: 10.5.2005

Репутация: нет
Всего: нет



Кажись понял всё. Только зачем разделили глобальные и публичные переменные? Последний вопрос-под глобальными переменными я так понимаю имелись ввиду переменные из раздела var в интерфейсной части?


--------------------
PM   Вверх
_hunter
Дата 2.9.2005, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

Репутация: 15
Всего: 98



в смысле разделили?


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
Alex
Дата 2.9.2005, 21:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4147
Регистрация: 25.3.2002
Где: Москва

Репутация: 80
Всего: 162



Цитата(tikitiki @ 2.9.2005, 16:34)
Посмотрел Help Delphi-так оказывается всё что не в определении процедуры или
функции -это называется глобальные переменные:т.е. в их число и public
входят(а также private и в интерфейсной Var части и т.д.). Ключевое слово global variables.

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


--------------------
Написать можно все - главное четко представлять, что ты хочешь получить в конце. 
PM Skype   Вверх
tikitiki
Дата 3.9.2005, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 330
Регистрация: 10.5.2005

Репутация: нет
Всего: нет



Извиняюсь. На злобу дня. Боюсь очень смешно выглядеть. Для связи между 2-мя Unit-ами может использоваться только всё, что объявлено в их интерфейсной части? И в конце концов где можно всё прочитать в одном месте,что касается этого вопроса и всё, что относится к подобным, я бы сказал, вопросам из азов? Я закачал недавно кучу faq по delphi, но ни один не устраивает. Ещё раз извиняюсь за индюшиный вопрос smile
(И на этот вопрос ответ ещё больше хочется получить, чем на сложные почему-то).


--------------------
PM   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1923 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.