Delphi | |
---|---|
Класс языка | императивный, структурированный, объектно-ориентированный, компонентно-ориентированный, высокоуровневый |
Появился в | 1995 |
Автор | Андерс Хейлсберг |
Расширение файлов |
.pas, .dpr, .dpk, .pp, .dproj, .dfm, .fmx, .bpl |
Выпуск | 12.2 Athens (3 сентября 2024 ) |
Система типов | статическая, сильная |
Основные реализации | Borland/Inprise/Codegear/Embarcadero Delphi; Borland Kylix; FreePascal |
Испытал влияние | Object Pascal, C++ |
Повлиял на | C#, Java[1] |
Сайт | embarcadero.com/ru/produ… |
Платформа | x86, x64, ARM |
ОС | Windows, macOS, iOS, Android, Linux |
Медиафайлы на Викискладе |
Delphi (Де́лфи, произносится /ˈdɘlˌfi:/[1]) — императивный, структурированный, объектно-ориентированный, высокоуровневый язык программирования со строгой статической типизацией переменных. Основная область использования — написание прикладного программного обеспечения.
Этот язык программирования является диалектом языка Object Pascal. Изначально язык Object Pascal относился к несколько другому языку, который был разработан в фирме Apple в 1986 году группой Ларри Теслера[2]. Однако, начиная с Delphi 7[3], в официальных документах компании Borland название Delphi стало использоваться для обозначения языка, ранее известного как Object Pascal.
Изначально среда разработки Delphi была предназначена исключительно для разработки приложений Microsoft Windows, затем был реализован вариант для платформ Linux (под торговой маркой Kylix), однако после выпуска в 2002 году Kylix 3 его разработка была прекращена, и вскоре было объявлено о поддержке Microsoft .NET, которая, в свою очередь, была прекращена с выходом Delphi 2007.
В настоящее время, наряду с поддержкой разработки 32 и 64-разрядных программ для Windows, реализована возможность создавать приложения для Apple macOS (начиная с Embarcadero Delphi XE2), iOS (включая симулятор, начиная с XE4 посредством собственного компилятора), Google Android (начиная с Delphi XE5)[4], а также Linux Server x64 (начиная с версии 10.2 Tokyo).
Независимая, сторонняя реализация среды разработки проектом Lazarus (Free Pascal, в случае компиляции в режиме совместимости с Delphi) позволяет использовать его для создания приложений на Delphi для таких платформ, как Linux, macOS и Windows CE.
Также предпринимались попытки использования языка в проектах GNU (например, Notepad GNU) и написания компилятора для GCC (GNU Pascal).
Используется для написания интернет сервисов IIS.
При создании языка (и здесь качественное отличие от языка C) не ставилось задачи обеспечить максимальную производительность исполняемого кода или лаконичность исходного кода для экономии оперативной памяти. Изначально язык ставил во главу угла стройность и высокую читаемость, поскольку был предназначен для обучения дисциплине программирования. Эта изначальная стройность в дальнейшем, как по мере роста аппаратных мощностей, так и в результате появления новых парадигм, упростила расширение языка новыми конструкциями.
Так, сложность объектного C++, по сравнению с Си, выросла весьма существенно и затруднила его изучение в качестве первого языка программирования, чего нельзя сказать об Object Pascal относительно Pascal.
Ниже перечислены некоторые отличия синтаксических конструкций Delphi от семейства C-подобных языков (C/C++/Java/C#):
dpr
(тогда как другие файлы исходных текстов программы имеют расширение pas).program Project32;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
begin
try
{ TODO -oUser -cConsole Main: Insert code here }
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
main
и определённым списком параметров, причём такая функция может быть расположена в любом из файлов исходного текста проекта.SomeVar
полностью эквивалентен somevar
. Регистро-зависимые идентификаторы в начале компьютерной эпохи ускоряли процесс компиляции, и кроме того, позволяли использовать очень короткие имена, порой отличающиеся лишь регистром. И хотя к настоящему времени обе эти практики — использование нескольких идентификаторов, различающихся лишь регистром, равно как и чрезмерная их лаконичность, — осуждены и не рекомендованы к применению, практически все унаследованные от С языки (C++, Java, C#) являются регистро-зависимыми, что, с одной стороны, требует достаточно большой внимательности к объявлению и использованию идентификаторов, а с другой — принуждает писать более строгий код, когда каждая переменная имеет чётко определённое имя (вариации регистра могут вызвать путаницу и ошибки)..pas
(которые, как правило, и содержат основное тело программы) на уровне языковых средств введено строгое разделение на интерфейсный раздел и раздел реализации. В интерфейсной части содержатся лишь объявления типов и методов, тогда как код реализации в интерфейсной части не допускается на уровне компиляции. Подобное разделение свойственно также языкам C, C++ или Rust, где в рамках культуры и парадигмы программирования вводится разделение на заголовочные и собственно файлы реализации, но подобное разделение не обеспечивается на уровне языка или компилятора. В C# же или Java такое разделение утрачено вовсе — реализация метода, как правило, следует сразу же после его объявления. Инкапсуляция обеспечивается лишь принадлежностью метода к той или иной области видимости. Для просмотра одной только интерфейсной части модуля исходного кода используются специальные средства.procedure
или function
, тогда как в C-подобных языках различие обуславливается типом возвращаемого значения: //Delphi
procedure DoSomething (aParam: Integer); //не возвращает значения
function Calculate (aParam1, aParam2: Integer): Integer; //возвращает целочисленный результат
//C#
void DoSomething(int aParam); // не возвращает значения
{
// code
}
int Calculate(int aParam1, aParam2); // возвращает целочисленный результат
{
// code
}
//C++: объявление типа pCalc, указателя на функцию-член, принимающую два целочисленных параметра и возвращающую целочисленный результат
typedef int (TSomeClass::*pCalc)(int, int);
typedef
. Имя типа, pCalc
, указывается в середине выражения, в скобках. //C#: объявление типа pCalc, указателя на функцию-член, принимающую два целочисленных параметра и возвращающую целочисленный результат
public delegate int pCalc(int aParam1, int aParam2);
delegate
, имя типа указывается в середине выражения. //Delphi
type pCalc = function(aParam1, aParam2: Integer): Integer of object;
type
, применением знака равенства (в случае переменной используется двоеточие), имя типа идёт сразу после ключевого слова.begin
и end
, тогда как в C-подобных языках программирования для этих целей используются фигурные скобки. Таким образом, возможно, в Delphi достигается лучшая читаемость кода для лиц с ослабленным зрением. С другой стороны, фигурные скобки могут быть более интуитивными при визуальном восприятии, выполняя функцию пиктограммы. //C#
if (bVal) {
//код, состоящий из нескольких инструкций
}
if (bVal2) /* код, состоящий из одной инструкции */;
//Delphi
if bVal then begin
// код, состоящий из нескольких инструкций
end;
if bVal2 then (* код, состоящий из одной инструкции *);
then
, что избавляет от необходимости заключать условие в круглые скобки.while (condition) { // цикл с "предусловием"
// тело цикла
};
do {
// тело другого цикла
} while (condition2); // конец цикла с "постусловием", тело выполняется хотя бы однажды
until
указывается условие выхода). while condition do begin//условием продолжения цикла является истинность выражения, следующего за словом while, как C/C#
//тело цикла
end;
repeat//начало цикла с постусловием
//тело цикла
until not condition2;//истинность выражения, следующего за словом until - это условие ВЫХОДА из цикла, в отличие от C/C#
:=
, что является заимствованием из математической нотации. Знак равенства без двоеточия — это оператор проверки равенства, возвращающий булево значение. Напротив, в C-подобных языках оператором присваивания является одинарный знак равенства, а оператором проверки равенства — двойной, ==
. В силу того, что в этих языках программирования присваивание является лишь выражением, возвращающим значение переменной слева, не так уж редки следующие неочевидные для новичка ошибки: // C++
int iVal = 12;
while (iVal = 1) {
// по замыслу программиста, данное тело цикла не должно выполняться, если на входе iVal имеет значение, отличное от единицы
// однако, в результате ошибочной замены знака == на одиночный =, iVal будет присвоено значение 1, а цикл окажется бесконечным
}
struct
, унаследованы от общего типа C#, несмотря на то, что сами по себе они не могут быть унаследованы (то есть, наследование структур в C# запрещено). Вместе с тем, экземпляры классов C# являются неявно-ссылочными типами, как и в Delphi.type
TAnimal = class abstract
protected
FPersonalName: string;
public
constructor Create(const PersonalName: string); virtual; abstract;
function GetSpecieName: string; virtual; abstract; // возвращает биологический вид животного
property Name: string read FPersonalName;
end;
TAnimalClass = class of TAnimal; // метакласс, могущий ссылаться на любой класс, унаследованный от TAnimal
...
function CreateAnAnimal(const FactAnimalClass: TAnimalClass; const Name: string): TAnimal;
begin
Result := FactAnimalClass.Create(Name); // функция не знает, животное какого именно вида будет создано, хотя "кличка" известна. Конкретная реализация вида скрыта.
end;
abstract
. Таким образом, в настоящее время классы, имеющие абстрактные методы (в отличие от ранних реализаций Delphi), не считаются абстрактными. При помощи механизма виртуальных функций код базового класса, имеющего абстрактные методы, определяет на этапе выполнения, перекрыт ли в фактическом экземпляре класса конкретный абстрактный метод, и в зависимости от этого или вызывает перекрытый метод, или создаёт исключение EAbstractError
. Также Delphi допускает перекрытие любого конкретного виртуального метода базового класса абстрактным в классе-потомке:type
TMyBase = class(TObject)
function A: integer; virtual; // метод A имеет реализованное тело в разделе implementation
end;
TMyDerived = class(TMyBase)
function A: integer; override; abstract; // метод перекрыт как абстрактный, тела не имеет,
// и при этом перекрывает (скрывает) реализованный в базовом классе
end;
procedure Test;
var m: TMyBase;
begin
m := TMyDerived.Create; // мы создали класс с абстрактным методом
m.A; // вызов A полиморфный, и мы получаем исключение типа EAbstractError, пытаясь выполнить абстрактный метод
end;
public class Date{//данный пример взят с [http://msdn.microsoft.com/en-us/library/w86s7x04.aspx msdn]
private int month = 7; // Backing store
public int Month{
get{ return month; }
set{
if ((value > 0) && (value < 13)) {
month = value;
}
}//set
}//prop
}//class
type
TDate = class
private
FMonth : Integer;
protected
procedure SetMonth(const Value: Integer); // реализация в разделе implementation
public
property Month: Integer read FMonth write SetMonth;
end;
type
TRectangle = class
private
FCoordinates: array[0..3] of Longint;
function GetCoordinate(Index: Integer): Longint;
procedure SetCoordinate(Index: Integer; Value: Longint);
public
property Left: Longint index 0 read GetCoordinate write SetCoordinate;
property Top: Longint index 1 read GetCoordinate write SetCoordinate;
property Right: Longint index 2 read GetCoordinate write SetCoordinate;
property Bottom: Longint index 3 read GetCoordinate write SetCoordinate;
property Coordinates[Index: Integer]: Longint read GetCoordinate write SetCoordinate;
end;
TMyObject = class
protected
function getStr(Name: string): string; virtual;
function getStrByIx(Index: Integer): string; virtual;
function getBy2Indicies(X, Y: Integer): string; virtual;
public
property Value[Name: string]: string read getStr; default;
property Value[Index: Integer]: string read getStrByIx; default;
property Value[X, Y: Integer]: string read getBy2Indicies; default; //количество
end;
Платформы .NET и Java значительно упростили разработку программ за счёт введения «сборщика мусора», который разрешает программисту не заботиться о высвобождении памяти, занимаемой объектами, которые вышли из области видимости работающего кода программы. Это, с одной стороны, значительно уменьшило проблему так называемых «утечек памяти» (когда уже ненужные, — и недостижимые по причине утраты адреса данные занимают оперативную память), но, с другой стороны, потребовало от платформы реализовать сложный и ресурсоёмкий алгоритм «сборки мусора» — который традиционно реализован как нахождение достижимых объектов и высвобождение остальных. На практике, чтобы выполнить исчерпывающий анализ достижимости объектов, сборщик мусора в некоторые моменты времени приостанавливает работу программы (всех её потоков), что приводит к кратковременной потере отзывчивости. Частота и длительность таких остановок напрямую зависит от объёма доступной оперативной памяти (пока есть свободная память, сборщик мусора старается не проводить блокирующий анализ), а также от числа задействованных в программе объектов (таким образом, лучше иметь несколько «больших» объектов, чем много — маленьких).
Ситуация ухудшается по мере роста количества задействованных в программе потоков — ведь исчерпывающий анализ достижимости требует полного останова. Таким образом, явная выгода — решение проблемы «утечек памяти» и, в целом, автоматическое управление временем жизни объектов — породила неявную проблему масштабирования и «провалов» производительности. Эта проблема малозаметна в простых программах, но по мере роста сложности и объёма кодовой базы становится всё более острой — то есть на финальном этапе разработки. Сложные программные комплексы, как правило, имеют привязку к реальному времени, так и требования к отзывчивости.
Точнее, когда у сборщика мусора есть в 5 раз больше памяти, чем требуется, его производительность совпадает или слегка превосходит прямое управление памятью. Однако, производительность сборщика мусора быстро деградирует, когда ему требуется работать с небольшими хипами. С 3 размерами требуемой памяти он, в среднем, работает на 17 % медленнее, а с двумя размерами — на 70 % медленнее. Также сборщик мусора более подвержен пейджингу, если память дефрагментирована. В подобных условиях, все протестированные нами сборщики мусора работают на порядок медленнее прямого управления памятью.Drew Crawford — Почему веб-приложения на мобильных платформах работают медленно
Попытки снизить издержки сборки мусора могут привести к существенному искажению стиля программирования[5][6]. В Delphi не существует автоматического управления памятью: (в классических компиляторах языка) экземпляры классов создаются и удаляются вручную, тогда как для некоторых типов — интерфейсов, строк и динамических массивов — задействован механизм подсчёта ссылок. Ни один из этих подходов, вообще говоря, не гарантирует отсутствия утечек памяти, но, с другой стороны, проблема отзывчивости неактуальна, временные издержки управления памяти малы, и, что важнее, очевидны. Также, при отсутствии утечек общий объём задействованной оперативной памяти существенно меньше, чем у аналогичных приложений, полагающихся на сборщик мусора.
Object Pascal — результат развития языка Турбо Паскаль, который, в свою очередь, развился из языка Паскаль. Паскаль был полностью процедурным языком, Турбо Паскаль, начиная с версии 5.5, добавил в Паскаль объектно-ориентированные свойства, а в Object Pascal — динамическую идентификацию типа данных с возможностью доступа к метаданным классов (то есть к описанию классов и их членов) в компилируемом коде, также называемую интроспекцией — данная технология получила обозначение RTTI. Так как все классы наследуют функции базового класса TObject, то любой указатель на объект можно преобразовать к нему, после чего воспользоваться методом ClassType и функцией TypeInfo, которые и обеспечат интроспекцию.
Также отличительным свойством Object Pascal от C++ является то, что объекты по умолчанию располагаются в динамической памяти. Однако можно переопределить виртуальные методы NewInstance и FreeInstance класса TObject. Таким образом, абсолютно любой класс может осуществить «желание» «где хочу — там и буду лежать». Соответственно организуется и «многокучность».
Object Pascal (Delphi) является результатом функционального расширения Turbo Pascal[7].
Delphi оказал огромное влияние на создание концепции языка C# для платформы .NET[источник не указан 4584 дня]. Многие его элементы и концептуальные решения вошли в состав С#. Одной из причин называют переход Андерса Хейлсберга, одного из ведущих разработчиков Дельфи, из компании Borland Ltd. в Microsoft Corp.
Delphi for .NET — среда разработки Delphi, а также язык Delphi (Object Pascal), ориентированные на разработку приложений для .NET.
Первая версия полноценной среды разработки Delphi для .NET — Delphi 8. Она позволяла писать приложения только для .NET. Delphi 2006 поддерживает технологию MDA с помощью ECO (Enterprise Core Objects) версии 3.0.
В марте 2006 года компания Borland приняла решение о прекращении дальнейшего совершенствования интегрированных сред разработки JBuilder, Delphi и C++ Builder по причине убыточности этого направления. Планировалась продажа IDE-сектора компании. Группа сторонников свободного программного обеспечения организовала сбор средств для покупки у Borland прав на среду разработки и компилятор[8].
Однако в ноябре того же года было принято решение отказаться от продажи IDE-бизнеса. Тем не менее разработкой IDE продуктов теперь будет заниматься новая компания — CodeGear, которая будет финансово полностью подконтрольна Borland.
В августе 2006 года Borland выпустил облегчённую версию RAD Studio под именем Turbo: Turbo Delphi (для Win32 и .NET), Turbo C#, Turbo C++.
В марте 2008 года было объявлено о прекращении развития этой линейки продуктов.
В марте 2007 года CodeGear порадовала пользователей обновлённой линейкой продуктов Delphi 2007 for Win32 и выходом совершенно нового продукта Delphi 2007 for PHP.
В июне 2007 года CodeGear представила свои планы, то есть опубликовала так называемый «roadmap»[9].
25 августа 2008 года компания Embarcadero, новый хозяин CodeGear, опубликовала пресс-релиз на Delphi for Win32 2009[10]. Версия привнесла множество нововведений в язык, как то[11]:
Вышедшая в 2011 году версия Delphi XE2 добавила компилятор Win64 и кросс-компиляцию для операционных систем фирмы Apple (MacOS X, iOS).
Вышедшая в 2013 году версия Delphi XE5 обеспечила кросс-компиляцию приложений для устройств на платформе ARM/Android.
Система типов в Delphi строгая, статическая.
Поддерживаются следующие типы данных:
Currency
вещественное фиксированной точности.string
— автоматический распределяемый в памяти, с подсчётом ссылок и парадигмой Copy-On-Write. В поздних версиях Delphi символы двухбайтные, Unicode-совместимые. AnsiString — аналогичная реализация для строк с шириной символа в один байт. Такие строки содержат в служебном поле информацию о кодировке. В Windows компиляторах с ранних версий существует тип WideString
, полностью совместимый типу BSTR
в Component Object Model. Также допускается использование строк с фиксированной длиной, не превышающей 255 однобайтных символов. Допускается использование примитивных строковых типов, в стиле языка C: PChar
и PWideChar
Variant
и OleVariant
— тип с динамической типизацией.Список операторов через пробел: :=
+ — * / div mod
not and or with xor
shl shr
^ = <>
>= <= < >
@ in is as
+
—
*
/
div
mod
Сложение, вычитание, умножение, деление(дающее вещественный результат), целочисленное деление, выделение остатка.По типу возвращаемого значения различаются операторы целочисленного деления (div
и mod
) и оператор /
. Последний, применяемый как к целочисленным, так и к вещественным операндам, всегда в результате даёт вещественный тип.
Оператор сложения +
используется также для конкатенации строк (когда используются встроенные строковые типы).
not
and
or
xor
Инверсия(отрицание), «И», «ИЛИ», Исключающее «ИЛИ». Тип операции (бинарная или логическая) зависит от типа первого операнда.К битовым операторам целочисленных типов относятся также shl
, shr
— операторы сдвига, соответствующие по смыслу одноимённым командам процессоров Intel x86.
=
<>
>
<
>=
<=
— равенства, неравенства(соответствует оператору !=
в C-подобных языках), больше, меньше, не меньше, не больше — применяются ко всем порядковым и вещественным типам и возвращают значение типа boolean
+
-
*
in
— сложение, вычитание, пересечение множеств, а также оператор теста вхождения, которые используются для манипуляций со встроенным типом множества. Первые три возвращают тип множества, последний — булевый тип.type
TDayOfWeek = (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); //задаётся тип перечислений
TDays = set of TDayOfWeek; //задаётся тип множества
var
day: TDayOfWeek;
days: TDays;
isMyDay: Boolean;
begin
days := [Sunday, Tuesday, Saturday];
day := Monday;
isMyDay := day in days; // оператор in возвращает булевое значение, принимая первым операндом значение типа "элемент множества", а вторым — значение типа "множество"
end;
()
as
is
— безусловное приведение, безопасное приведение объектных и интерфейсных типов, а также оператор теста принадлежности к типу(возвращает булевое значение). Безусловное(небезопасное) приведение используется в функциональном стиле(слева пишется идентификатор типа, справа в скобках приводимое к нему выражение) и применяется к порядковым, вещественным, структурным, ссылочным, строковым типам. При этом для ссылочных(включая неявно-ссылочные) типов не происходит действительного приведения, а лишь новая интерпретация тех же данных.Операторы as
и is
применяются к типам, допускающим полиморфное поведение — экземплярам класса и интерфейсам. Первый приводит безопасное(в смысле невозможности неверной интерпретации) приведение типа, а второй тестирует поддержку экземпляром класса или интерфейсом некоторого класса или интерфейса. Нужно помнить, что в отличие от языка C# неудавшееся приведение типа оператором as
возбуждает исключение.
^
@
— используются для работы с указателями.Оператор ^
разыменовывает указатель. Оператор @
выполняет обратное действие, возвращая адрес переменной. Поддерживается простые операции сложения и вычитания над типизированными указателями, с учётом размера типов, на которые они указывают (умная арифметика указателей).
:=
. В Delphi оператор присваивания, образует не выражение, а операцию, таким образом, не допускается «нанизывание» присваиваний.В языке Object Pascal классы — это специальные типы данных, используемые для описания объектов. Соответственно объект, имеющий тип какого-либо класса, является экземпляром (instance) этого класса или переменной этого типа.
Класс представляет собой особый тип, имеющий в своём составе такие элементы, как поля, свойства и методы. Поля класса аналогичны полям записи и служат для хранения информации об объекте. Методами называются процедуры и функции, предназначенные как правило для обработки полей. Свойства занимают промежуточное положение между полями и методами.
Объединение и скрытие объектных данных, а также обрабатывающих их методов, внутри конкретного класса от пользователя называется инкапсуляцией.
При создании новых типов объектов способность получить все свойства и методы от своих предков называют наследованием. Такие типы объектов наследуют после своего создания все поля, свойства, события, методы и прочее от своих предков. Наследование часто избавляет разработчиков от рутинной работы и позволяет, не мешкая, приступить к разработке чего-то нового. В отличие от C++, в Delphi не допускается множественное наследование. В Delphi есть возможность добавить методы в класс или запись, с помощью так называемого помощника класса или помощника записи (class helper или record helper), который, не являясь потомком от модифицируемого класса или записи, может добавлять в них дополнительные методы. Примером может служить объявленная в модуле System.SysUtils запись-помощник TStringHelper.
Delphi реализует классическую модель полиморфизма, принятую в прикладных языках программирования, когда методы базового класса, а также ссылочные переменные типа базового класса,— способны манипулировать экземплярами классов-потомков на основе контракта, заданного в базовом классе. Контрактом в этом случае выступает объявление абстрактных методов в базовом классе.
Каждая написанная программа на языке Delphi состоит из заголовка программы (program NewApplication;), поля используемых модулей Uses (к примеру, Uses Windows, Messages, SysUtils и т. д.), который может не входить в саму структуру, а также блоков описания и исполнения (начинаются составным оператором begin и заканчиваются end.).
program Project1; // Заголовок программы, с её именем «Project1»
uses
Forms,
Unit1 in 'Unit1.pas' {Form1}; // модули, которые подключены к проекту и используются программой
{$R *.res}
begin
Application.Initialize; // Инициализация приложения
Application.CreateForm(TForm1, Form1); // Создание формы/окна
Application.Run; // Запуск и исполнение
end.
Вывод сообщения «Hello, world!» в консольном приложении Delphi
program Helloworld; //название программы
{$APPTYPE CONSOLE} //директива компилятору о создании консольного приложения
begin
writeln('Hello, world!'); //вывод сообщения Hello, world!
readln; //ожидание нажатия клавиши пользователем
end. //конец программы
Вывод сообщения «Hello, world!» в 32-разрядном GUI приложении Delphi
...
procedure TForm1.Button1Click(Sender: TObject); //Обработчик события OnClick, генерируемый автоматически
begin
ShowMessage('Hello, world!'); //вывод сообщения Hello, world!
end; //конец процедуры
...
Динамическое создание списка строк и запись его в файл.
// Обработчик события, происходящего при создании формы MainForm
procedure TMainForm.FormCreate(Sender: TObject);
var
// Объявление переменной типа TStrings (список строк).
Strings: TStrings;
begin
// Создание (выделение памяти и заполнение её начальными значениями) объекта типа TStringList.
// TStringList - это потомок TStrings, реализующий его абстрактные методы с целью хранения строк в памяти.
Strings := TStringList.Create;
try
// Добавление строки.
Strings.Add('Добавляемая строка.');
// Сохранение всех строк в файл.
Strings.SaveToFile('C:\Strings.txt');
finally
// Освобождение памяти объекта и очистка ссылки на неё для предотвращения непреднамеренного обращения к не выделенной памяти.
FreeAndNil(Strings);
end;
end;
.pas
— исходный код модуля (pascal).dpr
— исходный код проекта (pascal).dproj
— исходный код проекта (xml).dproj.local
— исходный код проекта (xml).dfm
— исходный код формы.dpk
— исходный код проекта пакета.bpl
— скомпилированный пакет.dcu
— скомпилированный модуль.exe
— скомпилированное приложение.res
— ресурсы.dsk
— привязки к файлам.identcache
— кэшированные привязки к файламСреди многих распространённых программных продуктов, написанных на Delphi:[12]:
Возможно, этот раздел содержит оригинальное исследование. |
История критики Pascal восходит к 1981 году и работе Брайана Кернигана[16], аргументы которой в основном устарели по мере развития языка.
Некоторые изменения языка, осуществлённые компанией Embarcadero (разработчиком языка) в так называемых NextGen-компиляторах языка Delphi, намеренно нарушили совместимость с накопленной базой исходного кода. Эти изменения были отрицательно восприняты широким кругом опытных Delphi-разработчиков, поскольку, хотя и приближали язык к парадигме языков .NET, но сломали традицию высокой обратной совместимости и существенно затруднили перенос имеющегося исходного кода в программное обеспечение для мобильных платформ. Указанные ниже изменения поставили под сомнение самую парадигму мультиплатформенной разработки на базе единого исходного кода, рекламируемую Embarcadero.
Со времён Pascal исторически сложилось, что встроенный строковый тип индексировался с базой в единицу: «нулевой» элемент строки возвращал длину строки. По мере введения новых («длинных» и «юникодных») строковых типов данный порядок индексации сохранялся, обеспечивая почти бесшовный перенос кодовой базы на обновлённые версии языка. Однако со введением nextgen-компиляции парадигма изменилась: в новых компиляторах строки стали индексироваться по нулевой базе, как и в семействе С-подобных языков (C++, C#, Java), при этом в «классических» компиляторах для Windows и Mac OS парадигма единичной индексации была сохранена.
Исторически классы и их экземпляры являются неявно-ссылочными структурными типами. Тем не менее, управление временем жизни экземпляра класса изначально выполнялось вручную — посредством явного вызова конструктора и деструктора (либо метода Free()
), и такая особенность сохраняется (по состоянию на 2018 год) в классических версиях компиляторов. Подсчёт ссылок работал лишь для классов, реализующих интерфейсы, и притом, в том только случае, когда манипуляции с такими классами производились посредством переменных интерфейсного типа.
До версии 10.4 компиляторы для мобильных платформ ввели подсчёт ссылок для всех экземпляров классов, тем самым в корне изменив парадигму управлением временем жизни объектов, поскольку «ручное» управление практически (за исключением некоторых весьма продвинутых техник) несовместимо с новой парадигмой.
С версии 10.4 введен единый механизм управления памятью[17], когда для мобильных, настольных и серверных используется классическая реализация управления памятью объектов. ARC-модель управления памятью model осталась для управления строками и ссылками на тип интерфейса на всех платформах.
Многие разработчики рассматривают консервативность Delphi как достоинство, которое обеспечивает высокую переносимость кода, а также упрощает понимание языка начинающими программистами.
Однако в настоящее время ситуация такова, что новые технологии, парадигмы и даже языки программирования появляются (и набирают популярность) едва ли не каждый год. Развитие же языковых средств не всегда влечёт за собой отказ от обратной совместимости.
Ярким примером такого подхода является
До версии компилятора 33.0 (Delphi 10.3 Rio) объявление локальной переменной должно было предшествовать первой инструкции кода функции, причём инициализация локальных (стековых) переменных в месте объявления не допускается. Невозможен был также и вывод типа.
Для сравнения, объявление локальной переменной в любом месте функции поддерживалось в языке Си изначально, и было унаследовано практически всеми языками, которые придерживались Си-подобного стиля — C++, C#, Java и др.
Введение этого языкового средства в Delphi обсуждалось давно, но в то время не встретило понимания разработчиков языка.