With — Ключевое слово Delphi

Содержание

Зарезервированные слова Delphi

var A, B : Integer; begin A:=3; B:=4; A:=A*A+B*B; end;

if (условие) then (действие) else (альтернатива) ;

Слова if (если), then (тогда), else (иначе) — зарезервированные. Действие и else альтернатива — это любые операторы Delphi, или несколько операторов, заключённых в логические скобки begin/end, или вызов подпрограммы. Если условие истинно, то выполняется действие, если ложно, то выполняется альтернатива.

(применяется, когда известно количество повторений цикла)

for счётчик := выражение-1 to выражение-2 do действие ;

Возможна работа оператора цикла, при котором переменная-счётчик будет не увеличиваться, а уменьшаться. В этом случае ключевое слово to заменяется на downto:

for счётчик := выражение-1 downto выражение-2 do действие ;

Цикл с предусловием (применяется, когда неизвестно количество повторений цикла)

while условие do тело цикла ;

Этот цикл будет выполняться до тех пор, пока истинно условие (логическое выражение, возвращающее значение типа Boolean). При этом если это выражение сразу равно false, тело цикла не будет выполнено ни разу. Нужно очень внимательно следить за написанием условия и контролем завершения цикла, так как в результате ошибки цикл while будет повторяться бесконечное количество раз, что приведёт к «зацикливанию» и «зависанию» программы.

Цикл с постусловием

(применяется, когда неизвестно количество повторений цикла)

repeat тело цикла until условие ;

Повторения сначала выполняет тело цикла, а затем уже проверяет выполнение условия: Таким образом, этот вариант цикла гарантирует, что тело цикла будет выполнен по крайней мере один раз. И будет выполняться до тех пор, пока условие не станет истинным (т.е. true). Стоит отметить, что это единственный оператор Delphi, в котором тело цикла не требуется заключать в логические скобки begin/end. Начало и конец тела цикла определяются по ключевым словам repeat и until.

Позволяет изменить последовательность выполнения программы. В качестве метки может использоваться любой допустимый идентификатор или число в диапазоне от 0 до 9999. Метку предварительно необходимо объявить в разделе описания переменных, но с помощью не ключевого слова var, а ключевого слова label:

Является ли Delphi «с» ключевым словом плохая практика?

Я читал плохие вещи о ключе с в delphi, но, на мой взгляд, если вы не используете его. Это может сделать ваш код простым.

Я часто помещаю все свои TClientDataSets и TFields в TDataModules. Так что в моих формах у меня был код вроде этого

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

Мне кажется, что читать легче, используя ключевое слово с.

Не следует ли использовать ключевое слово с?

Самая большая опасность, связанная с такими патологическими состояниями, как «с A, B, C, D», заключается в том, что ваш код может молча изменить смысл без вашего уведомления. Рассмотрим этот пример:

Вы пишете этот код, зная, что Bar является свойством TFoo, а Baz является свойством типа, содержащего метод, который имеет этот код.

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

Ключевое слово с — это приятная функция, позволяющая сделать ваш код более удобочитаемым, но есть некоторые подводные камни.

Debugging:

При использовании этого кода:

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

Интерфейсы:

При создании интерфейса в предложении с он живет до конца вашего метода:

Ясность

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

Конечно, если у вас есть повторяющиеся имена, вы используете свойства и методы класса, объявленного в вашем операторе with (TMyForm).

У оператора with есть свое место, но я должен согласиться с тем, что чрезмерное использование может привести к двусмысленному коду. Хорошее эмпирическое правило состоит в том, чтобы убедиться, что код «более» доступен для чтения и поддержки после добавления оператора with. Если вы чувствуете, что вам нужно добавить комментарии, чтобы объяснить код после добавления инструкции, это, вероятно, плохая идея. Если код более читабельен, как в вашем примере, используйте его.

btw: это всегда был один из моих любимых шаблонов в Delphi для показа модального окна

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

Код Брайана кажется читабельным и приятным, но код будет короче, если вы просто придумаете отправителя напрямую, и вы устраните все сомнения по поводу того компонента, который вы включили:

Если вы беспокоитесь о многократном вводе, я предпочитаю временно ссылаться на объект с длинными именами:

Я не могу сказать, почему печатание должно вас беспокоить. Мы, во-первых, программисты, программисты Second, и завершение кода, копирование и запись клавиш могут помочь вам стать более эффективной машинистом.

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

Когда я впервые начал программировать на паскале (с TurboPascal!) и узнал, как я пошел, WITH казался замечательным. Как вы говорите, ответ на утомительную типизацию и идеально подходит для этих длинных записей. Поскольку Delphi прибыл, я удалял его и поощрял других отказаться от него — аккуратно подвел Verity в в регистре Помимо уменьшения удобочитаемости, есть две основные причины, по которым я мог бы избежать этого:

  • Если вы используете класс, тогда вам это все равно не нужно — только записи «кажутся» полезными.
  • Использование отладчика для выполнения кода с объявлением с помощью Ctrl-Enter не работает.

Тем не менее, для удобства чтения я все еще использую синтаксис:

Я не видел лучшей конструкции.

Ваш пример, доступ к датамному доступу в нажатие кнопки, на мой взгляд — плохо надуманный пример. Вся потребность в WITH уходит, если вы переместите этот код в модуль данных, где он должен быть. Затем OnClick вызывает LongNameDataModule.InsertStuff и нет необходимости.

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

Как упоминал Vegar, он так же аккуратен и намного читабельнее, легче отлаживается и менее подвержен проблемам скрытности, чтобы использовать временную ссылку.

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

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

Основная проблема с «с» заключается в том, что вы не знаете, где заканчивается его область действия, и вы можете иметь несколько совпадающих с операторами.

Я не думаю, что вам следует избегать его использования, если ваш код доступен для чтения.

Одно из предложений сделать его более читаемым (и менее запутанным в более длинном коде) было, если codegear добавила опцию , чтобы разрешить псевдонимы внутри, и, возможно, разрешить несколько сеансов в одном:

Насколько мне известно, With вполне приемлемо в том случае, когда вы даете. Это, безусловно, улучшает четкость кода.

Реальное зло — это когда у вас сразу несколько открытий.

Кроме того, мое мнение заключается в том, что то, что вы используете с on, имеет большое значение. Если это действительно другой объект, то с, вероятно, плохая идея. Тем не менее, мне не нравится иметь много переменных на одном уровне, даже если это имеет смысл — как правило, объекты данных, которые содержат весь очень сложный элемент данных, — это, как правило, весь фрагмент работы, для которой программа предназначена для работы. (Я не думаю, что этот случай произошел бы в приложении, у которого не было такого элемента.) Чтобы сделать мир более ясным, я часто использую записи для группировки связанных элементов. Я считаю, что почти все, с которыми я пользуюсь, предназначены для доступа к таким подгруппам.

Я твердо убежден в том, что удаляю поддержку WITH в Delphi. Ваш пример использования использования datamodule с именованными полями — это единственный экземпляр, который я мог видеть, что он работает. В противном случае лучший аргумент против него дал Крейг Стунц — который я проголосовал.

Я просто хотел бы отметить, что со временем вы можете (в конце концов) изменить все кодировки в событиях OnClick, и ваш код также в конечном итоге переместится от именованных полей в datamodules к использованию классов, которые обертывают эти данные, и причина использования WITH уйдет.

Ваш вопрос — отличный пример того, что «молот — это не всегда решение».

В этом случае «с» не является вашим решением: вы должны перенести эту бизнес-логику из своей формы в свой datamodule. Не делает этого, нарушает Закон Деметры, как mghie (Michael Hieke) уже прокомментировал.

Возможно, ваш пример был просто иллюстративным, но если вы действительно используете такой код в своих проектах, это то, что вы должны сделать вместо:

И затем назовите его из вашей формы следующим образом:

Это эффективно избавляет вас от вашего заявления и делает ваш код более удобным в обслуживании одновременно.

Конечно, окружающие строки Delphi с одинарными кавычками помогут скомпилировать его; -)

Здесь есть много превосходных ответов о том, почему утверждение with плохо, поэтому я постараюсь не повторять их. Я много лет использую эту инструкцию, и я очень сильно уклоняюсь от нее. Это частично из-за того, что может быть сложно разобраться в объеме, но в последнее время я начинаю заниматься рефакторингом, и ни один из автоматизированных рефакторингов не работает с выражением — и автоматическое рефакторинг является удивительным.

Также некоторое время назад я сделал видеоролик о том, почему утверждение with is bad, это не одна из моих лучших работ, но Здесь это

Используйте with только временно (так же, как вы закомментировать временно).

Это помогает вам писать эскизы кода, чтобы получить что-то скомпилированное и быстро выполняемое. Если вы консолидируете решение, очистите его! Удалить with , как вы переместите код в нужное место.

With — Ключевое слово Delphi

Прежде чем перейдем к дальнейшему описанию языка Delphi, формально опреде-
лим несколько терминов. Во-первых, это слово «идентификатор». Идентификатор —
это строка символов, используемая для именования некоторого элемента программы.
Это может быть переменная, запись, функция, процедура или конструкция более вы-
сокого уровня, например сама программа.
Идентификатор может иметь любую длину, однако в языке Delphi только первые
его 255 символов являются значимыми (что более чем достаточно!). Идентификатор
должен начинаться с буквы или символа подчеркивания (_) и не может содержать
пробелов. После первого символа идентификатора можно использовать буквы, цифры
и символы подчеркивания. Как и в зарезервированных словах, в идентификаторах
можно использовать как строчные, так и прописные буквы (компилятор их не разли-
чает). Приведенные ниже идентификаторы означают одно и то же.

CalculateValue
calculateValue
calculatevalue
CALCULATEVALUE
Ключевые слова не могут быть идентификаторами.
Далее рассмотрим лексемы. Это минимальные значимые единицы текста в про-
грамме. Они представлены такими категориями, как специальные символы, иденти-
фикаторы, метки, числа и строковые константы.
Программа, написанная на языке Delphi, состоит из лексем и разделителей, при-
чем разделитель представляет собой пробел или комментарий. Две соседних лексемы,
если они представляют собой зарезервированное слово, идентификатор, метку или
число, должны быть отделены друг от друга одним или несколькими разделителями.
В Delphi используются следующие подмножества набора символов кода ASCII.
• Буквы английского алфавита от А до Z и от а до z.
• Цифры — арабские цифры от 0 до 9.
• Шестнадцатеричные цифры — арабские цифры от 0 до 9, буквы от А до F и бу-
квы от а до f.
• Пробелы — символ пробела ($32) и все управляющие символы кода ASCII ($0-$31),
включая символ конца строки или символ возврата каретки ($13). Это шестна-
дцатеричные числа, так как перед ними стоит символ доллара «$».
Теперь определим смысл слова «выражение». Это фрагмент языка программирова-
ния, представляющий способ вычисления некоторого значения.
И наконец, определим смысл слов «операнд» и «оператор».
Операнд — часть выражения, над которым производятся операции. Например,
в выражении, присваивающем А сумму в и с (А := В+С;), А, в, с являются операн-
дами, а над значениями, представленными идентификаторами А й в , производится
операция суммирования. Идентификатор — это строка символов, используемая для именования некоторого
элемента программы.
Лексемы — это минимальные значимые единицы текста в программе.
Выражение — это фрагмент языка программирования, представляющий способ вы-
числения некоторого значения.
Операнд — часть выражения, над которым производятся операции.
Оператор — действие, которое может быть выполнено над одним или несколькими
операндами.
Оператор — действие, которое может быть выполнено над одним или несколькими
операндами. Если обратиться к вышеприведенному примеру, то оператором является
знак плюс (+). Хотя в некоторых случаях оператором можно назвать целое выражение,
заканчивающееся точкой с запятой. Более правильно такие операторы надо называть
структурированными операторами. Например, выражение
while i:=0 to 10 do x := i ;
можно назвать оператором, так как здесь выполняется операция цикла над пере-
менной X.
Теперь можно переходить непосредственно к ключевым словам. Обычно ключевые
слова пишутся строчными буквами, но Delphi безразличен к регистру клавиатуры, по-
этому можно использовать в своей программе как строчные (нижний регистр), так
и прописные (верхний регистр) буквы. Я рекомендую использовать какой-то один
стиль написания, например, тот, к которому вы уже привыкли. Но если вы только на-
чинаете программировать, то лучше использовать общепринятые правила и писать
ключевые слова строчными буквами. В табл. 3.1 приведен перечень всех ключевых
слов с кратким комментарием.
Таблица 3.1. Ключевые слова
Ключевое слово Комментарий
and Булев оператор И
array Массив
as Используется при проверке соответствия типов, определяет объект как операнд
asm Используется для выделения ассемблерного кода
begin Начало блока
case Оператор выбора. Используется при выборе из многих вариантов
class Определяет тип «класс»
const Определяет константы, т.е. неизменяемые переменные. Однако в Delphi есть
режим, допускающий изменение констант в теле программы
constructor Специальный метод класса, необходимый для создания и инициализации
экземпляра класса (объекта)
destructor Специальный метод класса, необходимый для разрушения объекта
d i s p i n t e r f a c e Определяет тип интерфейса
div Целочисленное деление
do Определяет начало исполнимой части в операторах цикла, конструкции
t r y . . . except и в операторе w i t h
downto Определяет направление итерации в операторе f o r
else Используется в операторах выбора case, условном операторе i f и в операторе
проверки исключений t r y . . .except
end
except
e x p o r t s
f i l e
f i n a l i z a t i o n
f i n a l l y
for
f u n c t i o n
goto
i f
implementation
i n
i n h e r i t e d
i n i t i a l i z a t i o n
i n l i n e
i n t e r f a c e
i s
l a b e l
l i b r a r y
mod
n i l
not
o b j e c t
of
or
out
Обычно используется совместно с ключевым словом begin и отмечает конец
блока. Также ставится в конце описания типа, например класса или записи
Используется в операторе проверки исключений t r y . . . except
Определяет список экспортируемых процедур, функций и переменных
Устанавливает тип переменной как файл. Используется при работе с файлами
Определяет начало раздела, который в программе всегда выполняется
последним
Используется в операторе проверки исключений t r y . . . f i n a l l y
Используется в операторах цикла f o r . . . to и f o r . . .downto
Используется при объявлении функций
Переход на метку
Используется в операторах выбора i f . . . then и i f . . . then. . .else
Определяет раздел реализации, в котором находятся описания процедур,
функций, методов и коды разрабатываемой программы
После этого ключевого слова может указываться путь к необходимому модулю.
Также используется при работе с множествами
Дословно можно перевести как «унаследованный». Используется при работе
с классами, поддерживая возможности полиморфизма
Определяет раздел инициализации, который всегда располагается перед
разделом f i n a l i z a t i o n . Если раздела f i n a l i z a t i o n нет, то раздел
инициализации находится перед завершением программы. Выполняется сразу
после запуска программы, перед всеми другими операторами. Обычно
используется для инициализации переменных
Используется при работе с ассемблерным кодом. Устаревшее ключевое слово
к применению не рекомендуется
Определяет тип интерфейса. Используется при опережающем объявлении
интерфейса
Используется при проверке типов
Метка. Используется совместно с ключевым словом goto. Может быть
выражена любым идентификатором или числом от 0 до 9999
Директива-напоминание или рекомендательная директива. Используется
наравне с директивами p l a t f o rm и deprecated для напоминания об
особенностях стандартных типов, методов или модулей. Во время компиляции
вызывает появление предупреждающего сообщения
Остаток от деления целых чисел
Специальная константа, которая может быть присвоена любому указателю,
после чего считается, что указатель не ссылается ни на что
Булев оператор отрицания
Используется как альтернатива слову class. Сохранено в языке для
совместимости со старыми версиями. Не рекомендуется к использованию
Используется во многих операторах как связующее ключевое слово
Булев оператор ИЛИ
Используется при объявлении параметров процедуры, функции или метода.
Предупреждает о том, что данный параметр используется только для
выдачи значений
packed
p r o c e d u r e
program
p r o p e r t y
r a i s e
r e c o r d
r e p e a t
r e s o u r c e s t r i n g
s e a l e d
set
shl
s h r
s t r i n g
then
t h r e a d v a r
t o
t r y
type
u n i t
u n t i l
uses
var
while
w i t h
xor
Используется для более плотного размещения данных в структурированных
типах (массивы, множества, записи, файлы, классы)
Используется при объявлении процедур
Определяет имя программы, которое должно быть выражено
идентификатором
Используется при объявлении свойств
Используется при генерации исключений
Определяет тип записи
Используется в операторе цикла repeat. . . u n t i l
Определяет раздел объявления ресурсов
Используется при объявлении класса, запрещая наследование данного класса
Ключевое слово для объявления множества
Логический оператор сдвига влево
Логический оператор сдвига вправо
Используется при объявлении строковых типов
Используется в операторах i f . . . then и i f . . . t h e n . . .else
Используется при разработке многопоточных приложений
Используется в операторе f o r . . . t o
Используется в операторе проверки исключений t r y . . . f i n a l l y ,
t r y . . .except и в операторе выбора case
Определяет раздел объявления типов
Модуль. Обычно это функционально законченный фрагмент программы,
сохраняемый в файле с таким же именем
Используется в операторе repeat. . . u n t i l
Определяет раздел подключаемых модулей
Определяет раздел переменных
Используется в операторе w h i l e . . . do
Используется для определения идентификатора, который всегда записывается
с другими идентификаторами. Код получается более компактным и понятным
Булев оператор Исключающее ИЛИ
Есть еще несколько ключевых слов, о которых мы поговорим при изучении объектно-
ориентированного программирования и которые могут использоваться как директивы.
Именно эти ключевые слова выделяются жирным шрифтом в редакторе кода, хотя
кое-что может вызвать недоумение: почему, например, слово Break, которое в других
языках программирования является ключевым, в редакторе кодов не подсвечивается?
В Delphi это не ключевое слово, а процедура, и для нее существует отдельное описа-
ние в библиотеке. А процедура write не описана в библиотеках, так как ее код встро-
ен в компилятор. Сейчас мы не будем разбираться в этих тонкостях, а только отме-
тим, что все ключевые слова обычно пишутся строчными буквами, а процедуры
обычно начинаются с прописной буквы.
Написание идентификаторов также можно сделать нагляднее, если использовать слова,
отражающие назначение идентификатора, и начинать каждое слово с прописной буквы.
Например, идентификатор для счетчика символов можно написать так: SymbolCounter. Здесь слова использованы полностью, а разделение достигается за счет того, что второе
слово начинается с большой буквы. Каждый, кто будет читать программу, где использо-
ваны подобные идентификаторы, сможет понять ее без дополнительных комментариев.
Используйте это правило, и ваши программы станут понятнее и для вас самих. (К сожа-
лению, все идентификаторы должны писаться только английскими буквами, поэтому
учите английский, в настоящее время это язык общения программистов.)

Илон Маск рекомендует:  Поле для игры в гомоку

Блог GunSmoker-а

. when altering one’s mind becomes as easy as programming a computer, what does it mean to be human.

22 декабря 2008 г.

Новое ключевое слово static в Delphi

Недавно я переводил пост Почему методы класса должны быть помечены словом «static», чтобы их можно было использовать в качестве функции обратного вызова? Реймонда Чена. Там я оставил весь код «как есть» — на C++. Здесь я рассмотрю этот вопрос с точки зрения Delphi.

Как известно, в языке есть такие сущности как процедуры/функции и методы. Причём начинающие программисты часто путают эти два понятия.

Функция (в дальнейшем здесь будет также подразумеваться и процедура) — это код. Процедурная переменная — это указатель на код. Например: Метод — это тоже код, но код, связанный с классом. Указатель на метод — это ссылка на код + ссылка на конкретный объект. Например: Когда путают одно с другим компилятор чаще всего показывает такое сообщение: «Incompatible types: regular procedure and method pointer». Чаще всего или забывают писать «of object» в объявлении своих процедурных типов или пытаются передать в функцию (чаще всего как callback — т.е. функцию обратного вызова) метод класса вместо обычной функции (а самым упорным это иногда удаётся).

Что делает эти две сущности такими принципиально несовместимыми? Функция — это просто код. Она не имеет связи с данными, отличными от тех, что передаются в её параметры. Методы класса помимо работы с параметрами (как и обычная функция) ещё могут оперировать с данными объекта (вот оно: «код» vs «код + данные»), например: С функциями такое невозможно — обратите внимание, как вы манипулируете с P3 (он же: Self.P3) в методе. Собственно сам объект (это встроенная переменная Self) неявно передаётся в метод первым параметром. Поэтому, если метод объявлен как function(const P1, P2: Integer): Integer of object — с двумя параметрами, то, на самом деле, он трактуется как функция с тремя параметрами: function(Self: TSomeObj; const P1, P2: Integer): Integer . Именно это различие (на бинарном уровне) делает несовместимыми обычные функции и методы.

Соответственно, указатель на обычную функцию — это просто указатель (pointer), только что типизированный (это я про TDoSomethingFunc) — т.е. 4 байта. А вот указатель на метод — это уже запись или, если будет угодно, два указателя — один на код, второй — на данные, т.е. всего 8 байт.

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

Ещё в Delphi есть классовые методы. Это такие методы, которые можно вызывать не имея на руках объект. В этом случае вместо объекта в неявный параметр Self передаётся информация о классе. Т.е. в классовых методах вы не можете использовать информацию о конкретном объекте (например, читать/писать его поля), но можете использовать информацию о классе — например, вызывать конструктор класса. Также методы класса могут быть виртуальными. Заметим, что сигнатура функции, реализующей метод, всё ещё совпадает с сигнатурой обычного метода: неявный параметр (данные класса вместо Self) + все явные параметры метода.

Например: Теперь ещё один шажок и мы переходим к тому, о чём говорил Реймонд Чен. Классовый метод можно объявить статическим (только в новых версиях Delphi). В этом случае у него не будет неявного параметра. Разумеется, при этом он не может использовать информацию экземпляра и класса. Зато он и не отличается от обычной функции.

Рассматривая пример с потоком, вот что мы могли бы написать в старых Delphi без поддержки статических классовых методов: Теперь, с введением нового ключевого слова static, появилась возможность писать так: При этом Реймонд говорит о том, что если у Execute сделать модель вызова stdcall, то бинарные сигнатуры параметра CreateThread, методов ThreadProc и Execute совпадут — поэтому, мол, умный компилятор уменьшит код ThreadProc до простого jmp. Увы, но компилятор Delphi не настолько умён — в этом случае он генерирует полный вызов вместе с передачей параметра.

With — Ключевое слово Delphi

Данная книга — продолжение предыдущей книги автора, «Delphi. Только практика». Также как и в «Delphi. Только практика», в данном издании подробно рассмотрены программы для сетей, различные шуточные программы, простые игрушки, некоторые полезные приложения, разработка приложений в стиле Windows XP. В частности, здесь можно найти такие примеры как бесплатная отправка SMS, FTP-клиент, простое шифрование, CGI-сценарии и многое другое. Описаны методы работы с системным реестром Windows и INI-файлами, а также некоторые важные аспекты программирования на системном уровне с применением функций Windows API. Для облегчения понимания программ каждый пример содержит комментарии сложных строк кода.

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

Книга: Delphi. Учимся на примерах

Конструкция with-do

Для упрощения программного кода при работе с записями и классами в языке Object Pascal используется конструкция with-do. Например, фрагмент кода

MyCD.Group:= ‘Название группы’;
MyCD.Year:= 2005;
MyCD.Title:= ‘Название альбома’;
Form1.Caption:= ‘Заголовок формы’;
Form1.Font.Color:= clWhite;

можно записать в виде:

with MyCD do begin
Group:= ‘Название группы’;
Year:= 2005;
Title:= ‘Название альбома’;
end;
with Form1 do begin
Caption:= ‘Заголовок формы’;
Font.Color: = clWhite;
end;

Еще один вариант записи этого же фрагмента:

with MyCD, Form1 do begin
Group:= ‘Название группы’;
Year:= 2005;
Title:= ‘Название альбома’;
Caption:= ‘Заголовок формы’;
Font.Color:= clWhite;
end;

При такой записи подстановка имен объектов осуществляется в порядке их следования. Однако в этом случае требуется следить за тем, чтобы для объектов, указанных после слова with, не использовались поля, свойства или методы с одинаковыми названиями, поскольку это может привести к путанице.

Программирование на языке Delphi. Глава 2. Основы языка Delphi. Часть 1

Оглавление

В основе среды Borland Delphi лежит одноименный язык программирования — Delphi, ранее известный как Object Pascal. При разработке программы среда Delphi выполняет свою часть работы — создает пользовательский интерфейс согласно вашему дизайну, а вы выполняете свою часть — пишите обработчики событий на языке Delphi. Объем вашей работы зависит от программы: чем сложнее алгоритм, тем тяжелее ваш труд. Необходимо заранее усвоить, что невозможно заставить средство разработки делать всю работу за вас. Некоторые задачи среда Delphi действительно полностью берет на себя, например создание простейшей программы для просмотра базы данных. Однако большинство задач не вписываются в стандартные схемы — вам могут понадобиться специализированные компоненты, которых нет в палитре компонентов, или для задачи может не оказаться готового решения, и вы вынуждены будете решать ее старым дедовским способом — с помощью операторов языка Delphi. Поэтому мы настоятельно рекомендуем вам не игнорировать эту главу, поскольку на практике вы не избежите программирования. Мы решили изложить язык в одной главе, не размазывая его по всей книге, чтобы дать вам фундаментальные знания и обеспечить быстрый доступ к нужной информации при использовании книги в качестве справочника.

Алфавит


Буквы

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

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

Буквы — это прописные и строчные символы латинского алфавита и символ подчеркивания:

Цифры представлены стандартной арабской формой записи:

применяются в основном в качестве знаков арифметических операций, разделителей, ограничителей и т.д. Из специальных символов формируются составные символы :

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

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

Числа

Одно и то же число можно записать самыми разными способами, например:

В языке Delphi имеется возможность применять все способы записи, но чаще всего используют целые и вещественные числа.

Целые числа состоят только из цифр и знака + или -. Если знак опущен и число не равно 0, то оно рассматривается как положительное, например:

Вещественные числа содержат целую и дробную части, разделенные точкой:

Вещественные числа могут быть представлены в двух формах: с фиксированной и плавающей точкой.

Форма с фиксированной точкой совпадает с обычной записью чисел, например:

Форма с плавающей точкой используется при работе с очень большими или очень малыми числами. В этой форме число, стоящее перед буквой E, умножается на 10 в степени, указанной после буквы E:

Число, стоящее перед буквой E, называется мантиссой , а число после буквы E — порядком .

В этой статье мы чаще будем использовать форму с фиксированной точкой, так как она воспринимается лучше второй формы и совпадает с привычной математической записью чисел.

Слова-идентификаторы

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

При написании идентификаторов могут использоваться как прописные, так и строчные буквы (между ними не делается различий). Длина идентификатора может быть любой, но значимы только первые 255 символов (вполне достаточный предел, не так ли). Примеры написания идентификаторов приведены ниже:

Правильно


Неправильно


RightName Wrong Name E_mail E-mail _5inches 5inches

Все идентификаторы подразделяются на зарезервированные слова, стандартные директивы, стандартные идентификаторы и идентификаторы программиста.

Зарезервированные (ключевые) слова составляют основу языка Delphi, любое их искажение вызовет ошибку компиляции. Вот полный перечень зарезервированных слов:

Стандартные директивы интерпретируются либо как зарезервированные слова, либо как идентификаторы программиста в зависимости от контекста, в котором используются. Вот они:

Илон Маск рекомендует:  Атрибут bgproperties в HTML

Стандартные идентификаторы — это имена стандартных подпрограмм, типов данных языка Delphi, т.д. В качестве примера приведем имена подпрограмм ввода и вывода данных и нескольких математических функций. Вы, без сомнения, сами угадаете их назначение:

Идентификаторы программиста определяются программистом, т.е вами, и носят произвольный характер. Если идентификатор состоит из двух или более смысловых частей, то для удобства их лучше выделять заглавной буквой или разделять символом подчеркивания:

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

Комментарии

С помощью комментариев вы можете пояснить логику работы своей программы. Комментарий пропускается компилятором и может находиться в любом месте программы. Комментарием является:

Данные


Понятие типа данных

Программа в процессе выполнения всегда обрабатывает какие-либо данные. Данные могут представлять собой целые и дробные числа, символы, строки, массивы, множества и др. Так как компьютер всего лишь машина, для которой данные — это последовательность нулей и единиц, он должен абсолютно точно «знать», как их интерпретировать. По этой причине все данные в языке Delphi подразделены на типы. Для описания каждого типа данных существует свой стандартный идентификатор: для целых — Integer, для дробных — Real, для строк — string и т.д. Программист может образовывать собственные типы данных и давать им произвольные имена (о том, как это делается, мы поговорим чуть позже).

Тип данных показывает, какие значения принимают данные и какие операции можно с ними выполнять. Каждому типу данных соответствует определенный объем памяти, который требуется для размещения данных. Например, в языке Delphi существует тип данных Byte. Данные этого типа принимают значения в целочисленном диапазоне от 0 до 255, могут участвовать в операциях сложения, вычитания, умножения, деления, и занимают 1 байт памяти.

Все типы данных в языке Delphi можно расклассифицировать следующим образом:

  • простые типы данных. Они в свою очередь подразделяются на порядковые и вещественные типы данных. К порядковым типам относятся целочисленные, символьные, булевские, перечисляемые и интервальные типы данных;
  • временной тип данных. Служит для представления значений даты и времени;
  • строковые типы данных. Служат для представления последовательностей из символов, например текста;
  • составные типы данных (в некоторых источниках — структурированные типы данных). Формируются на основе всех остальных типов. К ним относятся массивы, множества, записи, файлы, классы и ссылки на классы;
  • процедурные типы данных. Позволяют манипулировать процедурами и функциями как данными программы;
  • указательные типы данных. Данные этих типов хранят адреса других данных, с их помощью организуются различные динамические структуры: списки, деревья и т.д.;
  • тип данных с непостоянным типом значений. Служит для представления значений, тип которых заранее неизвестен; с его помощью легко организуется работа со списком разнотипных значений;

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

По ходу изложения материала мы рассмотрим все перечисленные типы данных и более подробно объясним их смысл и назначение в программе.

Константы

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

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

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

Очевидно, что, изменив базовую константу SecondsInMinute, можно изменить значение константы SecondsInDay.

При объявлении константы можно указать ее тип:

Такие константы называются типизированными; их основное назначение — объявление константных значений составных типов данных.

Переменные

Переменные в отличие от констант могут неограниченное число раз менять свое значение в процессе работы программы. Если в начале программы некоторая переменная X имела значение 0, то в конце программы X может принять значение 10000. Так бывает, например, при суммировании введенных с клавиатуры чисел.

Переменные описываются с помощью зарезервированного слова var . За ним перечисляются идентификаторы переменных, и через двоеточие указывается их тип. Каждая группа переменных отделяется от другой группы точкой с запятой. Например:

В теле программы переменной можно присвоить значение. Для этого используется составной символ :=, например:

Вы можете присвоить значение переменной непосредственно при объявлении:

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

Каждый используемый в программе элемент данных должен быть описан в разделе const или var . Исключение составляют данные, заданные непосредственно значением , например:

Простые типы данных


Целочисленные типы данных

Целочисленные типы данных применяются для описания целочисленных данных. Для решения различных задач могут потребоваться различные целые числа. В одних задачах счет идет на десятки, в других — на миллионы. Соответственно в языке Delphi имеется несколько целочисленных типов данных, среди которых вы можете выбрать наиболее подходящий для своей задачи.

With — Ключевое слово Delphi

В первую очередь пошел искать в хелпе, не нашел (хотя узнал много интересного ^^), в яндексе тоже глухо. В книжках по делфи, которые мне попадались о сабже тоже нет упоминаний. Итак, что же делает ключевое слово «object»? Ссылки на документацию приветствуются, но и ответом «своими словами» не побрезгую.

ЗЫ В общем-то, какой-то конкретной цели не преследую, просто для повышения образованности.

Это устаревший способ работы с самодельными объектами. Теперь гораздо целесообразнее использовать class

> Это устаревший способ работы с самодельными объектами

Моё любопытсво все еще не удовлетворено :). Чем object отличается от class, что именно устарело. Попадался мне как то код с этим волшебным словом, так что хотелось бы понять что это из себя представляет.

Идеальное слово для описания всего.

Даже для искуственного интелекта.

> Desdechado © (03.03.07 17:06) [1]
> Это устаревший способ работы с самодельными объектами. Теперь гораздо целесообразнее использовать class

В Делфях классом считается все, что прождено от TObject. Но проблема в том, что нужно было объявить сам TObject в юните «system.pas», для чего и использовали ключевое слово языка Паскаль object. Ключевое слово class не является зарезервированным словом языка Паскаль, хотя поддерживается и зарезервировано сейчас почти всеми компиляторами (Delpi, FPC, Lazarus, Kylix, TNT).


> Чем object отличается от class, что именно устарело

object в общем-то позволяет создать статический объект. Подробнее о нем ты лучше прочитай в любом руководстве по Турбо-Паскалю 5.5-7.0, с тех пор ничего не изменилось. В Delphi object только для совместимости и поддерживается

Руководство щас погуглю.
А под статическим объектом понимается объект, все методы которого статические? А конструктор с деструктором присутствуют? (=

Servelat © (03.03.07 17:19) [6]
нет просто память под такой объект выделяется статически, то есть при загрузке программы в память, а не когда программист соизволит

> PEAKTOP © (03.03.07 17:14) [4]
TObject = class;
T >
купи «твикс». жуй. молчи. заодно почитай материалы по Object Pascal (тому, из которого упёрли концепцию обёектов в Turbo Pascal 5.5).

Собственно, вопрос закрыт; нашел у себя на винте UserGuide по BP70 (что прям удивительно, на русском), где тема полностью раскрыта, просвещаюсь. Всем спасибо за ответы.

Удобен тем, что содержит в себе идеи ООП (наследование) и не требует лишней работы и памяти. Посмотри, сколько всего делается и создается в конструкторе TObject! Если мне нужно будет использовать сотню-другую тысяч объектов, то выбор будет за object»ами, а не за классами, наверное.

> Если мне нужно будет использовать сотню-другую тысяч объектов,
> то выбор будет за object»ами, а не за классами, наверное.

Так и до record»a дойти не долго :))

> Ketmar © (03.03.07 17:34) [8]

> Loginov Dmitry © (03.03.07 18:58) [11]

Структурное программирование рулит. Я серьезно.


> Посмотри, сколько всего делается и создается в конструкторе
> TObject! Если мне нужно будет использовать сотню-другую
> тысяч объектов, то выбор будет за object»ами, а не за классами,
> наверное.

Гм. Наверное наооборот :-) class как раз под такие случаи и заточен :-)

> tesseract © (03.03.07 20:52) [14]

На пустых объектах/классах поэкспериментировал, 100000000 TObject»ов создано за 19 секунд и использовано 720 метров памяти, столько просто обджектов — за ноль секунд и использовано памяти метр с копейками. Если объекты буду содержать какие-то данные и выполнять какие-то действия, то и на сотне разницу почуствуем.

> использовано памяти метр с копейками

Сами-то в это верите?

> Если объекты буду содержать какие-то данные и выполнять
> какие-то действия, то и на сотне разницу почуствуем.

Или эта разница просто-напросто исчезнет.

> Сами-то в это верите?

Четырехзначная цифирь, начинается на один .

to PEAKTOP © (03.03.07 17:14) [4]:
Что за трава? Или это были грибы? :)))

to TUser © (03.03.07 21:04) [15]:
>На пустых объектах/классах поэкспериментировал
Угу, а производительность будем на «Hello, World!» мерять. :)
Пустой object занимает 0 байт, в отличие от наследника TObject, который занимает 4 минимум байта.

>Если объекты буду содержать какие-то данные и выполнять какие-то
>действия, то и на сотне разницу почуствуем.
Фиг. Если в object будет поле, допустим integer, вес уравняется. Преимуществ не будет почти никаких. При одинаковом количестве полей будут те самые 400 байт на сотне.

И вообще, что-то цифры подозрительные. Что там в коде-то?

TUser © (03.03.07 21:04) [15]

Тут такой момент — пустые объекты, как и пустые классы никому не нужны. Давай ты полные насоздаешь ?

33 секунды для объектов vs минута думанья и Out of memory в случае классов :) Объекты и классы содержали по два поля типа integer + то, что от TObject. Говорю же — объекты (те, которые экземпляры классов) память любят кушать. Больше, чем объекты, которые просто, т.е. типа record с наследованием.

> Говорю же — объекты (те, которые экземпляры классов) память
> любят кушать. Больше, чем объекты, которые просто, т.е.
> типа record с наследованием.

Ай-ай! Какая беда! 100000000 объектов всю память скушали!
Только нюансик один: что вообще в принципе можно делать с таким количеством объектов? Их же надо где-то индексировать (в массиве там, или в списке), это еще 400 метров памяти надо. Нужен метод доступа, поиска и т.п., что при таком количестве объектов (будь то object или class) будет выполняться катастрофически долго.
То есть пример со 100000000 объектов выглядет очень уж надуманным.

to TUser © (04.03.07 04:27) [21]:
>Говорю же — объекты (те, которые экземпляры классов) память любят
>кушать. Больше, чем объекты, которые просто, т.е. типа record с
>наследованием.
А вот мои подсчеты говорят, что памяти в результате понадобится одинаковое количество. Догадываетесь, почему? А времени, тут да, создание экземпляра класса требует чуть больше, т.к. экземпляру класса требуется инициализация, а у object её по-умолчанию нет, но это опять же, до тех пор пока там данных в нормальном количестве нет.

Поэтому еще раз говорю, что-то там не то с методикой. Код в студию.

Чтобы вопросов не возникало:

uses
SysUtils,
Windows;

type
Cls = class
a,b: integer;
end;

PObj = ^Obj;
Obj = object
private
a,b: integer;
end;

procedure AllocCls(count: integer);
var
i: integer;
begin
for i := 0 to Count — 1 do
Cls.Create;
end;

procedure AllocObj(count: integer);
var
i: integer;
o: PObj;
begin
for i := 0 to Count — 1 do
new(o);
end;

var
T1, T2, T3: Cardinal;
S1, S2, S3: Cardinal;
begin
T1 := GetTickCount;
S1 := GetHeapStatus.TotalAllocated;
AllocCls(10000000);
S2 := GetHeapStatus.TotalAllocated;
T2 := GetTickCount;
AllocObj(10000000);
S3 := GetHeapStatus.TotalAllocated;
T3 := GetTickCount;
writeln(Format(«%d %d», [T2-T1, S2-S1]));
writeln(Format(«%d %d», [T3-T2, S3-S2]));
readln;
end.

Результат (CoreDuo 6600 2.4 ГГц, RAM 2ГБ):
500 120000000
109 120000000

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

Но проблема в том, что нужно было объявить сам TObject в юните «system.pas», для чего и использовали ключевое слово языка Паскаль object

О как. Оказывается, object использовали для создания class. Вот так и возникают религии. Хвала всевышнему, объект придумавшему, ибо класс и экземпляр класса — суть порождение его. Во имя object, class и instance его! Аминь.

Я, наверное, еретик. бо у меня возник вопрос, откуда же в таком случае взялся сам object :0)

и если от record»а, то откуда взялся record? и так далее. )

to Virgo_Style © (04.03.07 12:29) [26]:
>откуда взялся record?
record был всегда :)

record придумал Вирт, а Вирта придумали мама с папой. выводы очевидны :)

хех
неужто настолько делать нефига людям что ещё не влом думать о такой архаике как object:)

> PEAKTOP © (03.03.07 19:03) [12]
расслабься. приведённый мной код — цитата из system.pas. советую перед тем, как вещать, таки читать генофонд. ну и — да, язык, о котором вещаешь, тоже выучить бы не помешало.

>>неужто настолько делать нефига людям что ещё не влом думать о такой архаике как object:)
что за наезды на обжект? фундаментальная штука. это класс придумка борланда, насколько помню в стандарте паскаля нет такого словечка:)

object — это отнюдь не архаика.

Во-первых, без слова object затруднительно определить callback типа

type
TForProgressBar = procedure(Current, Total: Integer) of object;

Это, ясное дело, очень мощное и «современное» средство, не реализованное, к примеру, в С++. Там аналог убогий.

Во-вторых, object позволяет создавать «интеллектуальные записи» (с методами), которые к тому же обладают свойством наследования. В некоторых диалектах С я встречал это свойство «наследования» с применением анонимных структур.

> просто так (04.03.07 14:07) [32]
я-таки скажу откровение: в том стандарте и object ни разу нет.


> я-таки скажу откровение: в том стандарте и object ни разу
> нет

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

_uw_ (04.03.07 14:08) [33]
ну я не про все применения ключевого слова object, а именно про то применение которое оставлено для совместимости

в .NET структуры наделённые свойствами ООП юзаются порой в качестве «легковесных» объектов ибо для них в стеке память выделяется(то есть быстро) и освобождается быстро(а не когда GC соизволит)
в каком-то таком же смысле использования object-объектов возможно и может быть оправдано

Расставляем точки над i в Delphi RAII

Тема RAII в Delphi обычно замалчивается или же информация по этому вопросу ограничивается обсуждением полезности интерфейсов. Но интерфейсы поодиночке не дают многих желаемых возможностей. Когда в Delphi 2006 появилась перегрузка операций, приватные поля записей, собственные конструкторы и методы в записях и, казалось, было бы логично увидеть и автоматически вызываемый деструктор. И run-time позволяет, и в разделе запроса новых фич Delphi на протяжении нескольких лет в ТОП–10 висит запрос №21729 «Record Operator Overloading: Please implement «Initialize» and «Finalize» operators». Наверное, не судьба. Ничего, я покажу, как обойтись без несостоявшихся фич. Так как Delphi 7 живее всех живых, будут рассмотрены решения, совместимые с Delphi 7 в том числе

Времени найти обходные пути было достаточно. Эта статья — не tutorial и рассчитана на продвинутых разработчиков на Delphi, пишущих собственные библиотеки или делающих привязки к библиотекам на других языках программирования

Зачем хочется RAII в Delphi?

  • Автоматическое управление памятью. Лестница из try… finally — это не серьёзно. TList, TComponentList и прочие требуют дисциплины от того, кто будет их применять. Особенно сложно, не используя автоматику, сделать корректное освобождение памяти для переменных, используемых из восходящего замыкания
  • Copy-on-write и счётчики ссылок
  • Другое особое поведение при копировании
  • Copy-on-write и счётчики ссылок для объектов, созданных в сторонних библиотеках (например, CFString)

Для каких типов Delphi действует автоматическое управление?

  • AnsiString, WideString, UnicodeString — строки
  • array of… — динамические массивы
  • reference to… — замыкания в Delphi 2009+
  • интерфейсы
  • Variant, OleVariant — варианты

Среди всех этих возможностей программируемыми являются только интерфейсы и варианты

Чем плохи интерфейсы?
  • Инициализируются nil, у которого нельзя вызывать методы.
    Не подходит, если вы хотите реализовать собственный тип строки или собственную длинную арифметику. Неинициализированная переменная должна вести себя как пустая строка или 0, соответственно
  • Методы не могут изменить содержимое переменной–указателя, у которого они были вызваны
  • Нет контроля за тем, что происходит при копировании объекта. Только AddRef, который не может изменить содержимое переменной–указателя
  • Нет встроенной возможности сделать copy-on-write
  • Нет перегрузки операций
Чем плохи варианты?
  • Инициализируются Unassigned, у которого также нельзя вызвать методы
  • Вызовы нетипизированы. Реализация IDispatch или диспетчеризации у вариантов — нетривиальная и слабо документированная область знаний
  • Необходимость реализации муторных конверсий между другими типами вариантов, всяческих вспомогательных методов, которые могут быть вызваны

Как решить большинство этих проблем?

Решение, которое я предлагаю — заворачивать интерфейсы или варианты внутрь приватной части записей (record). Объявляем тип записи. Объявляем тип интерфейса. Дублируем все методы и в интерфейсе, и в записи. Методы записи перенаправляют все вызовы внутреннему объекту, при этом можно сделать то, что сама по себе переменная интерфейсного типа сделать не способна

В реализации каждого метода записи предусматриваем случай, когда в приватном поле nil — может потребоваться автоматически инициализировать объект перед тем, как что–либо вызывать у него. Если нужно реализовать Copy-on-write, в интерфейсе объявляется метод

Этот метод определяет по счётчику ссылок свою уникальность. Если объект не уникален, объект должен создать свою копию и записать этот указатель в Obj вместо себя. Каждый метод записи, который может что–либо изменить, перед передачей управления методу интерфейса должен убедиться в уникальности указателя. Для внутренних нужд можно и у других методов интерфейса предусмотреть var Obj: IOurInterface. Например, по аналогии со встроенными строками может возникнуть желание сделать так, чтобы, когда в строке собственного типа не остаётся символов, динамически размещённый объект удалялся, а внутренний указатель становился nil

В целях оптимизации при реализации собственных строк или длинной арифметики может потребоваться предусмотреть специальный случай a := a + b. Не гарантирую, что это сработает, но можно попробовать при реализации операции + сравнивать указатели @ Self и @ Result

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

Вариант в записи — это как зефир в глазури, но вариант в записи

Собственный тип варианта даёт более полное управление по сравнению с интерфейсом. Так как вариантное поле приватно и наружу этот вариант не должен утекать, можно реализовать лишь минимальный набор методов собственного (custom) типа варианта. Если не считать отладчика, пытающегося привести (CastTo) вариант к строке при наведении курсора, потребуется реализовать копирование (Copy) и уничтожение (Clear) варианта. В оперативной памяти собственные типы варианта, как правило, состоят из маркера типа варианта и указателя (например, наследник TObject). Как это делается, предлагаю посмотреть на примере реализации комплексных чисел (VarCmplx.pas), который присутствует, по крайней мере, начиная с Delphi 7

Использование вариантов пригодилось бы для однозвенной обёртки CFString. Если делать обёртку для интерфейсов, Delphi будет вызывать AddRef и Release у интерфейса, но CFString — не интерфейс, и потребуется либо обернуть CFString в дополнительный слой косвенности из интерфейса, либо использовать собственный тип варианта, который вызывает CFRetain и CFRelease, требуемые для нормального управления памятью CFString. Это работало бы гораздо лучше, чем та обёртка CFString, которую предлагает Embarcadero в Delphi XE2

Эй, а как же Delphi 7?

Delphi — язык с длинной историей, и до того, как появилась объектная система Delphi, в Borland Pascal with Objects была другая объектная система. В Delphi 7 и Delphi 2005 она по–прежнему функционирует. Вместо record пишется ключевое слово object, и получившийся тип во многом похож на record в Delphi 2006: у него могут быть приватные поля, у него могут быть методы. object’ы одного типа можно присваивать друг другу, в этом смысле они тоже аналогичны record. Как раз то, что нам нужно. Компилятор будет ругаться на небезопасный тип, нет перегрузки операций, но это единственные неудобства. Сходство object и record настолько велико, что можно, используя условные директивы компилятора, на старых версиях Delphi объявлять тип как object, а на новых — как record. Именно так я поступил в своей небольшой библиотеке коллекций Delphi-CVariants

Проблемы могут возникнуть, если пытаться объявить несколько таких типов, использующих друг друга. Цикличные зависимости в исходном коде предусмотрены для классов, интерфейсов и указателей, но не для object’ов as is. Предпочтительнее объявлять object’ы так, чтобы каждый следующий знал про предыдущие, но не наоборот. Поэтому, например, в моей библиотечке CMapIterator знает про CVariant, но CVariant не знает про CMapIterator

delphi — Что такое ключевое слово inline в delphi

может кто-нибудь сказать, что такое использование встроенного ключевого слова в delphi

    4 5
  • 6 апр 2020 2020-04-06 16:10:18
  • Anonymous

5 ответов

Нажмите Ctrl + Alt + C (полное окно отладки CPU) во время отладки в Delphi, прежде чем вызывать свою встроенную функцию. И вы увидите, что встроенные функции запускаются без «вызова» и wo перехода на другой адрес. Это функция оптимизации.

  • 6 апр 2020 2020-04-06 16:10:19
  • Alex

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

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

Где это сделать? Ну, как петля, она разматывает эту технику, которая очень редко используется в наши дни. Классическое место для использования этого — глубокая вложенная структура, которая является критически важной в реальном времени, например, рендеринг кода в графическом приложении, где несколько машинных вызовов, сбритых на каждой итерации, могут увеличить частоту обновления экрана.

With — Ключевое слово Delphi

В математических выражениях используются операции присваивания , , , , , целочисленного , остатка от . При использовании этих операций важен приоритет их выполнения, так как в программировании на языке Delphi, как и в обычной математике, выражения выполняются не в порядке следования, а с учётом приоритета. У операций умножения и деления более высокий приоритет, чем у операций сложения и вычитания.
То есть, результат выражения

будет равен не 1, как в случае последовательного выполнения, а 6.2 .

Если же мы хотим получить именно последовательное выполнение, то необходимо применять скобки (), обособляющие те операции, которые необходимо выполнить первыми. Скобки могут быть вложены друг в друга неограниченное число раз:

Вот теперь X будет равен 1.

Помимо четырёх математических действий в Delphi доступно множество математических функций, таких, например, как тигонометрические, логарифмические, и т.д. Они становятся доступны в программе после добавления в секцию Interface uses модуля Math. Их описание также можно найти в модуле Math.pas (можно найти воспользовавшись поиском Windows). Многие из них можно реализовать и самому, но встроенные функции наверняка будут работать быстрее и лучше, т.к. написаны на языке ассемблера.

Логические выражения

Операторы Delphi

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

  • оператора присваивания
  • условного оператора
  • оператора цикла

С оператором присваивания «:=» мы уже знакомились в уроке Delphi 2. Он работает следующим образом. Переменная, стоящая в левой части оператора, становится равной той величине, которая находится справа. Типы этих величин должны совпадать. В выражении, стоящем справа, также может использоваться переменная, стоящая слева. С математической точки зрения это неправильно, но в программировании это означает, что из ячейки памяти берётся исходное значение, производятся вычисления, и результат записывается в эту же ячейку памяти, затирая прежнее значение. Пример:

В начале фрагмента переменная A равна 3, а в конце -25.

Условный оператор позволяет изменить порядок выполнения операторов в зависимости от выполнения некоторого условия. Вот как он записывается:

if условие then действие else альтернатива ;

Слова if (если), then (тогда), else (иначе) — зарезервированные. Действие и else альтернатива — это любые операторы Delphi, или несколько операторов, заключённых в логические скобки begin/end, или вызов подпрограммы. Если условие истинно, то выполняется действие , если ложно, то выполняется альтернатива .
Условие представляет собой логическое выражение. В нём сравниваются значения выражений (в том числе также и логических), вызов функций, возвращающих значения типа Boolean, и комбинирование этих значений с помощью логических операций:

Знак
операции
Название операции Логические операции могут комбинироваться с помощью связок:
and (логическое И)
or (логическое ИЛИ)
xor (исключающее ИЛИ)
Для некоторых типов данных есть дополнительные операции. Например, для множеств — оператор in, которая проверяет, входит ли некоторое значение в множество. Например:
X := [2, 4, 5, 7, 8, 10] ;
Выражение 2 in X истинно (имеет значение true);
Выражение 6 in X ложно (имеет значение false);
= Равно
<> Не равно
> Больше
= Больше или равно
действие ;
Счётчик — это переменная, которая должна быть объявлена перед логическим блоком, в котором оператор цикла расположен, и её тип должен относиться к одному из перечислимых типов, обычно Integer.
Выражение-1 и выражение-2 могут быть как константой или идентификатором, так и вызовом функции.
Действие — один или несколько операторов Delphi. Если это группа операторов, то они должны быть заключены в логические скобки begin/end.
В начале работы оператора переменная-счётчик получает значение выражения-1 . Если при этом значение счётчика окажется меньше или равно значению выражения-2 , то выполняются операторы, входящие в действие . Это и есть один цикл. Затем переменная-счётчик принимает значение, следующее за текущим, и начинается новый цикл, то есть сравнение счётчика и выражения-2 , выполнение действия , и так далее, до тех пор, пока значение переменной-счётчика не превысит значение выражения-2 .
Возможна работа оператора цикла, при котором переменная-счётчик будет не увеличиваться, а уменьшаться. В этом случае ключевое слово to заменяется на downto:
for счётчик := выражение-1 downto выражение-2 do действие ;
Соответственно, выражение-1 должно быть больше или равно выражению-2 .

Условный оператор цикла удобно использовать в том случае, когда количество повторений заранее не известно:
while условие do
тело цикла ;
Этот цикл будет выполняться до тех пор, пока истинно условие (логическое выражение, возвращающее значение типа Boolean). При этом если это выражение сразу равно false, тело цикла не будет выполнено ни разу.
Нужно очень внимательно следить за написанием условия и контролем завершения цикла, так как в результате ошибки цикл while будет повторяться бесконечное количество раз, что приведёт к «зацикливанию» и «зависанию» программы.

Условный оператор повторения сначала выполняет тело цикла , а затем уже проверяет выполнение условия :
repeat
тело цикла
until условие ;
Таким образом, этот вариант цикла гарантирует, что тело цикла будет выполнен по крайней мере один раз. И будет выполняться до тех пор, пока условие не станет истинным (т.е. true). Стоит отметить, что это единственный оператор Delphi, в котором тело цикла не требуется заключать в логические скобки begin/end. Начало и конец тела цикла определяются по ключевым словам repeat и until.

Вместе с операторами цикла используются специальные команды:

  • команда прерывания цикла
  • команда продолжения цикла

Команда прерывания цикла применяется, если в процессе выполнения операторов тела цикла выясняется необходимость его завершения. Вот эта команда:
Break ;
При её выполнении управление передаётся на первый оператор, следующий за оператором цикла.
Команда продолжения цикла позволяет немедленно продолжить выполнение цикла, пропустив все оставшиеся операторы в теле цикла, то есть начать следующую итерацию . Вот эта команда:
Continue ;

Справедливости ради стоит рассказать об ещё одном операторе, позволяющем изменить последовательность выполнения программы. Это оператор перехода:
goto метка ;
В качестве метки может использоваться любой допустимый идентификатор или число в диапазоне от 0 до 9999. Метку предварительно необходимо объявить в разделе описания переменных, но с помощью не ключевого слова var, а ключевого слова label:
label меткa ;
или
label список меток ;

Переходить можно как вниз, так и вверх по программе. Двоеточие отделяет метку от оператора, на который производится переход. Пример использования оператора перехода:

Из этого примера видно, что оператор end ; завершающий программу, никогда не будет выполнен, то есть программа зациклится. Именно поэтому, вообще, использование оператора перехода является плохим стилем программирования, и без его использования вполне можно обойтись использованием условных операторов и операторов цикла. Единственный случай, когда использование оператора goto может быть оправдано — это выход из нескольких вложенных циклов, что иначе требует применения нескольких операторов Break.

Пример. Сортировка одномерного массива

Рассматриваются процедуры программы, приводятся подробные комментарии. Также можно скачать проект в виде архива. Цикл while и операторы goto использованы только для демонстрации работы с ними. Здесь — более правильный вариант с применением цикла repeat и оператора break.
Параллельно замечу, что сортировка массива «методом пузырька» — неэффективный метод. Количество итераций (проходов цикла) растёт гораздо быстрее роста количества элементов, . Сортировка 50 000 элементов выполняется на моём компьютере секунд за пять. Но сортировка 100 000 — не за 10 секунд, а около 35 секунд! Можете поэкспериментировать, для этого достаточно во 2 варианте установить в описании массива нужное количество элементов.

Илон Маск рекомендует:  Распахивающееся модальное окно
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL