Страница 1 из 2

uses - почему так?

СообщениеДобавлено: 23.03.2019 12:17:47
DedFrend
Конвертируя чужой проект из Delphi в Lazarus, натолкнулся на одну вещь, которая мне показалась странной.
Речь пойдет о случае, когда в разных модулях присутствует одно и то же имя. По правилам Паскаля в этом случае используется то, которое стоит после в предложении uses.
Но в Delphi/Lazarus есть два uses. Мною экспериментально установлено, что в этом случае приоритет имеет секция Imlementation, причем и в Delphi и в Lazarus.
А вот это мне кажется неестественным. Ведь объявление в interface обязательно, если используешь что-то в своем интерфейсе. А в implementation можно поместить модуль из-за того, что в реализации потребовалась единственная функция из его состава. Но кроме этой функции в модуле может оказаться куча всего и эта куча получает приоритет и может перекрыть описания объявленные в интерфейсе.
Я не понимаю - зачем так сделано ?
И уж, чтобы оправдать тему форума: проблема перекрытия имен мне кажется решена плохо. Кстати, я даже не знаю утилиты, которая бы искала и предупреждала о подобных проблемах. Я бы предложил дополнительный описатель в объявление модуля (возможно, необязательный):
unit [ private, imported, system] в смысле private - твой личный, Imported - сторонний, System - системный. И при конфликте имен приоритеты в том же порядке.

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

Re: uses - почему так?

СообщениеДобавлено: 23.03.2019 13:41:48
Лекс Айрин
Все просто. Есть секции импорта/ экспорта и реализации. Реализация это внутренняя кухня, т.е. там только то, что может потребоваться для самого модуля. Секция интерфейса это то, что требуется преимущественно самому компилятору, что бы найти нужные функции типы и пр...
Вообще, лучше не использовать подключение модулей в реализации. Это реализовано для тех случаев, когда нужно использовать модули рекурсивно ссылающиеся друг на друга.
Вообще-то, описание не уникальных имён в одном проекте моветон. А предполагаемый тобой функционал реализован на уровне объектов.

Re: uses - почему так?

СообщениеДобавлено: 23.03.2019 15:54:29
DedFrend
Мой вопрос прежде всего - Почему реализация имеет приоритет на интерфейсом? В чем причина?

Лекс Айрин писал(а):А предполагаемый тобой функционал реализован на уровне объектов.


И каким же образом? Чем конфликты имен у классов отличаются от переменных или процедур?

Re: uses - почему так?

СообщениеДобавлено: 23.03.2019 16:03:07
Снег Север
DedFrend писал(а):Почему реализация имеет приоритет на интерфейсом? В чем причина?

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

Re: uses - почему так?

СообщениеДобавлено: 23.03.2019 16:54:44
Лекс Айрин
DedFrend, а подумать?
Я уже сказал почему. Потому что это резервное место подключения модулей, которые определены рекурсивно. Грубо говоря, это обход правила, что модуль не может ссылаться сам на себя, даже по цепочке зависимостей. Данная фишка используется редко, если правильно спроектировать структуру модулей. Обычно, для ликвидации такой зависимости, надо просто выделить часть модулей в отдельный модуль или тупо их объединить. Я, например, использовал объявление в реализации чтобы ссылаться на главную форму, но потом переделал прогу так, что бы все переменные, которые влияют на состояние главной формы, собрались в модуле глобальных переменных. Сюда же добавилось все, что должно инициироваться до запуска программы. Спасибо zub-у, что мозги вправил.
Конечно,стало чуть сложнее, но зато всегда можно вместо изменения кучи мест изменить одно, а уже потом спокойно пересчитать настройки. Возможно для оптимизации я потом и верну определение модуля в реализации, хотя сильно сомневаюсь.

Re: uses - почему так?

СообщениеДобавлено: 23.03.2019 18:07:13
Sergei I. Gorelkin
На самом деле, не "реализация имеет приоритет над интерфейсом", а приоритет имеет описание, встреченное последним. Можно иметь два юнита с одинаковым типом в секции implementation, по умолчанию будет применяться тип из второго.

Re: uses - почему так?

СообщениеДобавлено: 23.03.2019 19:30:05
Лекс Айрин
Sergei I. Gorelkin, тут ещё есть один момент. В реализации можно использовать модули, которые вызовут ошибку встретившись в интерфейсе. И будет не то чтобы ошибкой, но недостатком использование подключения модулей в реализации.
Кстати, первоначально возможность подключения модулей в реализации появилась ещё в турбопаскале. Толи в 6, толи в 7 версии. Хотя не исключаю, что и раньше. Так что тут можно уже говорить о преемственности.

Re: uses - почему так?

СообщениеДобавлено: 23.03.2019 23:12:13
DedFrend
Спасибо за активность, НО есть ли какие-то соображения ПОЧЕМУ приоритет имеет реализация?
Лекс Айрин! Что implementation uses какой-то костыль вы совершенно неправы. Во-первых, если имя используется только в реализации, то и незачем его тащить в интерфейс . Многие оптимизаторы (да как бы и не Лазаревый) об этом предупреждают и предлагают перенести объявление в реализацию. Во-вторых, это общий принцип - открывай только то, что действительно необходимо. Я согласен, что циклические ссылки можно разрулить изменив структуру связей, но менять структуру - это работа и часто непростая. А мой вопрос возник вообще при преобразовании чужого модуля. Мне очень не хочется копать его структуру (там 6000 строк!).
Горелкин намекает, что "кто последний тот и папа", но это и само по себе плохо, а тут еще внутренняя секция имеет приоритет над внешней.

Я еще могу понять такой ответ "потому что так в Delphi" , но коснувшись преобразований вижу, что в Лазаре очень многое "совсем не так как в Delphi", так что это тоже слабый аргумент.

Re: uses - почему так?

СообщениеДобавлено: 24.03.2019 07:46:26
Лекс Айрин
DedFrend, вообще-то компилятор может скомпилировать модуль в объектный код, оставив в отдельном файле интерфейс с твоим расчетом, что его можно будет подключить к иному проекту. В лазарусе это не развито, все собирается из исходников, но для ускорения сборки такие объектные модули тоже присутствуют.
Если подумаешь, то сможешь понять, что два места для подключения модулей это слишком много.
Да, циклические связи разрывать тяжело, но это они сильно запутывают программу, не позволяют отладить все по частям. Точнее, сильно это затрудняют.

Re: uses - почему так?

СообщениеДобавлено: 24.03.2019 22:21:27
zub
DedFrend
Последнее упоминание имеет приоритет - имхо логично и правильно. Но уповать на это и искать тут какую то прибыль совсем не стоит - отстрелишь себе яйца по самые ноги.
Давай разные имена, не допускай двойственности и зависимости от порядка упоминания в усес.

>>Горелкин намекает, что "кто последний тот и папа", но это и само по себе плохо
что именно плохо и как надо?

>>а тут еще внутренняя секция имеет приоритет над внешней.
не имеет она приоритета, приоритет выходит из цитаты выше

Re: uses - почему так?

СообщениеДобавлено: 25.03.2019 14:31:34
wavebvg
"Кто последний, тот и папа" определяется тем, что область видимости у нас не декларированная, а стековая. Это относится ко всем именованным объектам: т.е. не только для функций и секции uses, но и для переменных, функций, констант, включая локальные функции и переменные методов, их аргументы. В общем любая именованная сущность может быть подменена при последующей декларации (переменная может стать константой или даже функцией).
Логичность и "нелогичность" может быть "спорной", но данный подход обеспечивает максимальную гибкость и гарантирует отсутствие пагубной связности для локальных методов модуля.

Re: uses - почему так?

СообщениеДобавлено: 25.03.2019 16:13:25
stanilar
DedFrend писал(а):Я не понимаю - зачем так сделано ?


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

Не помню, было-ли такое правило в Паскале(и если было, то в какой версии), но можно еще объявить uses между procedure - begin. Вот это было действительно очень практично, когда uses в implementation был объявлен только для конкретной процедуры. Но честно уже не вспомню где это было, на работе я больше не паскалист.

Re: uses - почему так?

СообщениеДобавлено: 25.03.2019 17:59:35
Лекс Айрин
stanilar, я бы не сказал, что это очень удобно. Скорее всего попробовали, но не пошло. Слишком пришлось бы усложнять код компилятора. Даже просто подключение одного модуля в реализации должно усложнить компиляцию файла. Да и достигаемых целей можно достичь через прямое указание модуля из которого берется нужный тип, переменная или объект. Что более похоже на стандартный паскаль.

Re: uses - почему так?

СообщениеДобавлено: 26.03.2019 12:19:31
stanilar
Лекс Айрин писал(а):я бы не сказал, что это очень удобно


Это было логичным и естественным в цепочке файлы-секции файла-процедуры. Без лишних синтаксических наворотов.

Re: uses - почему так?

СообщениеДобавлено: 26.03.2019 14:16:17
Лекс Айрин
stanilar, а ты уверен, что модуль не понадобится где-то еще? Точнее, его содержимое.