Продолжается подписка на наши издания! Вы не забыли подписаться?

Borland Delphi 8

Авторы: Голованов Михаил
Веселов Евгений

Платформа создания приложений .NET, активно продвигаемая Microsoft, находит все больше приверженцев среди программистов благодаря удобству, гибкости и широким возможностям. Понятно, что и другие производители средств разработки, например, Borland, не собираются оставаться в стороне от этого. Первый шаг в завоевании симпатий .NET-программистов фирма Borland сделала, создав C# Builder, продукт для разработки .NET-приложений на языке C#. Однако Borland не остановился на этом. Совсем недавно фирмой была представлена восьмая версия популярной среды разработки Delphi. Слухи о новых возможностях восьмой версии давно будоражили умы разработчиков, бета-версии Delphi демонстрировались на различных презентациях, таких как Borland Developer Day, однако обстоятельно поработать с Delphi 8 все никак не удавалось. Наконец, Delphi 8 вышла в свет, что дало возможность «пощупать» продукт и поделиться с читателями свежими впечатлениями. При написании статьи использовалась версия Delphi Architect.

Прежде всего стоит отметить, что Delphi 8 предназначена только для создания приложений для .NET. Однако, по заявлениям Borland, вместе с восьмой версией будет поставляться и предыдущая, седьмая версия, ориентированная на разработку Win32 приложений.


Рисунок 1.

Новая IDE

Первое, что бросается в глаза при запуске новой версии Delphi – это новый стиль IDE (Integrated Development Enviroment). Фирма Borland активно унифицирует IDE своих продуктов. Новая IDE Delphi аналогична IDE C# Builder.

Внесенные изменения носят не только и не столько косметический характер. Фирма Borland, как и обещала, переходит от использования IDE к UDE (Unified Development Enviroment) – унифицированной среде разработки. О многом говорит хотя бы тот факт, что для новых продуктов C# Builder и Delphi выделена отдельная папка Program Files\Borland\BDS. C# устанавливается в подпапку 1.0, а Delphi – в 2.0. Использование UDE дает несколько преимуществ:


Рисунок 2.

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

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

Редактор кода также обзавелся новыми возможностями. Самое заметное и весьма удобное дополнение – возможность минимизировать блок текста. В качестве блоков текста выступают: секции декларации (interface) и реализации (implementation), декларация класса, текст метода класса и т. д.

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

Еще одним приятным нововведением редактора стала возможность настройки подсветки синтаксиса. Поддерживается подсветка языков Delphi, C#, C++, XML/HTML, кроме того, возможно настроить опции редактирования для каждого из языков.


Рисунок 3.

Окно шаблонов кода (CodeSnippets) позволяет создавать повторно используемые шаблоны исходного кода. Такая возможность была и ранее, однако теперь CodeSnippets вынесены в отдельное окно, и пользоваться ими, на мой взгляд, стало удобнее.

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

Не может не радовать добавление возможностей интеграции с системами контроля версий. У предыдущих версий Delphi встроенные возможности работы с системами поддержки версий были довольно слабы, что приводило к необходимости использовать для решения этой задачи продукты третьих фирм. В восьмой версии реализована поддержка взаимодействия с системами контроля версий через Microsoft SCC API. Поддерживаются следующие популярные системы контроля версий:

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


Рисунок 4.

Общие возможности

Delphi 8 позволяет разрабатывать приложения WinForms, ASP.NET, WebServices, компоненты для WinForms и Web с использованием всех возможностей .NET Framework. Другими словами, Delphi8 позволяет разрабатывать все виды .NET-приложений.

Кроме того, на платформу .NET была портирована родная объектная библиотека VCL, получившая имя VCL.NET. Перенесен также набор компонентов Indy для работы с сетью и генератор отчетов RaveReports.

Дальнейшее развитие получила технология создания приложений Bold. Bold был портирован на платформу .NET и получил название ECO (Enterprise Core Object).

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

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


Рисунок 5.

Новые возможности языка Delphi

Необходимость поддержки возможностей .NET привела к значительному изменению языка Delphi. Ниже приведено краткое описание внесенных в язык изменений.

Пространства имен

Стандартным контейнером типов в Delphi является юнит (unit). В .NET реализована другая система организации хранения типов – пространства имен. Необходимость работы с классами .NET потребовала введения в Delphi поддержки пространства имен. В отличие от юнитов, пространства имен имеют иерархическую структуру. Наличие иерархии пространства имен позволяет исключить неоднозначность в определении типов данных, имеющих одинаковое текстовое имя.

Вот что сказано в документации о пространствах имен.

В Delphi 8 файл проекта неявно объявляет новое пространство имен, называемое пространством имен проекта по умолчанию (project default namespace).

Например строка:

program MyProgram;

Объявляет пространство имен MyProgram.

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

unit MyUnit;

Поддержка иерархии пространства имен обеспечивается разделением точкой частей иерархии:

unit MyNamespace.MyUnit;

В данном примере объявлено пространство имен MyUnit, вложенное в пространство имен MyNamespace. При этом файл, в который будет сохранен юнит, будет называться MyNamespace.MyUnit.pas. Глубина иерархии пространства имен не ограничена.

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

program MyProgram;

содержащий юнит

unit MyUnit;

Тогда юнит будет иметь пространство имен MyProgram.MyUnit, файл юнита будет называться MyUnit1.pas, а компилироваться модуль будет в файл MyProgram.MyUnit.dcuil.

Регистр символов в имени пространства имен не учитывается.

Пространство имен может иметь алиас – короткое название, объявленный после ключевого слова as:

uses MyCompany.AVeryLongNamespaceDesignation.VeryDescriptiveUnitName as aUnit;

В данной декларации объявлен алиас aUnit для пространства имен MyCompany.AVeryLongNamespaceDesignation.VeryDescriptiveUnitName.

При сборке проекта компилятор использует следующий порядок поиска пространств имен:

  1. Текущее пространство имен юнита.
  2. Пространство имен проекта.
  3. Пространства имен перечисленные после ключевого слова namespaces в объявлении проекта.
  4. Пространства имен прописанные в настройках компилятора.

А теперь скажем о результатах наших маленьких экспериментов.

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

Второй тонкий момент использования пространств имен, несколько озадачивший нас – автоматическое включение модуля в пространство имен проекта. Так, в документации утверждается, что если имя модуля не содержит полного имени пространства имен, то оно включается в пространство имен проекта. Мы создали простой проект WinFormsApplication, содержащий файл проекта Project1 и одну форму. Заголовок юнита формы unit WinForm; Казалось бы, что в соответствии с документацией классы юнита должны содержаться в пространстве имен Project1.WinForm. При этом файл winform.pas должен быть скомпилирован в файл project1.winform.dcuil. Мы никак не могли понять, а что же нам делать, если мы хотим чтобы классы юнита не включались в пространство имен пректа, а были корневым элементом нового пространства имен WinForm. А что случится, если создать еще один юнит с формой и назвать его project1.winform.pas, не будет ли конфликта имен?

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

WinForm in 'WinForm.pas' {WinForm.TWinForm: System.Windows.Forms.Form}

Модуль компилируется в файл winform.pas и никак не конфликтует с классами модуля unit Project1.WinForm;

В общем, кому верить? Своим глазам или документации от Borland? Мы не пока не знаем.

Новые модификаторы области видимости

Объектная модель Delphi ранее позволяла получать доступ к protected- и private-членам класса из других классов, объявленных в том же модуле. Модификатор strict, появившийся в восьмой версии запрещает такое поведение. Например, объявив класс, мы говорим Delphi, что процедура Dispose не может быть вызвана другими классами, даже если они будут объявлены в том же модуле:

TWinForm = class(System.Windows.Forms.Form)
  strict private
  strict protected
    procedure Dispose(Disposing: Boolean); override;
  end;

Статические поля, методы и свойства класса

Ранее можно было объявлять в классе лишь статические методы класса (class method), теперь объявить статическим можно поле, и даже свойство. Ниже приведены примеры такого объявления.

type
  TMyClass = class
    strict private
      class var
      FX: Integer;
         
    strict protected
      // Accessor-ы для свойств класса должны быть объявлены как class static
      function GetX: Integer; static;
      procedure SetX(val: Integer); static;

    public
      class property X: Integer read GetX write SetX;
      procedure StatProc(s: String); static;
  end;

Статические конструкторы класса

Статический конструктор класса выполняется перед тем, как класс будет использован. Он должен быть объявлен в секции strict private. Класс имеет только один статический конструктор без параметров потому, что он вызывается CLR при первом обращении к типу. При наследовании не нужно в теле статического конструктора вызывать статический конструктор предка, используя inherited. Компилятор это сделает за вас сам. Пример объявления статического конструктора:

type
  TMyClass = class
    strict private
      class var
        class constructor Create;
  end;

Вложенные типы данных

Введена поддержка вложенных типов, вложенные типы являются частью .NET. Синтаксис объявления вложенного типа:

type
  className = class [abstract | sealed] (ancestorType)
    memberList

    type
      nestedTypeDeclaration 

      memberList
  end;    

Классы с запретом наследования

Для поддержки классов .NET с запретом наследования было добавлено ключевое слово sealed. Класс, объявленный как sealed, не может иметь наследников. Синтаксис объявления:

type
  className = class [abstract | sealed] (ancestorType)
    memberList
  end;

Финальные виртуальные методы

Виртуальный метод может быть объявлен с модификатором final. Такие методы не могут быть перекрыты в потомках класса.

Перегрузка операторов

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

Symbol Mapping Сигнатура Категория
implicit typecast Implicit(a : type) : resultType; Приведение
explicit typecast Explicit(a: type) : resultType; Приведение
- Negative(a: type) : resultType; Унарный
+ Positive(a: type): resultType; Унарный
Inc Inc(a: type) : resultType; Унарный
Dec Dec(a: type): resultType Унарный
not LogicalNot(a: type): resultType; Унарный
not BitwiseNot(a: type): resultType; Унарный
Trunc Trunc(a: type): resultType; Унарный
Round Round(a: type): resultType; Унарный
= Equal(a: type; b: type) : Boolean; Сравнение
<> NotEqual(a: type; b: type): Boolean; Сравнение
> GreaterThan(a: type; b: type) Boolean; Сравнение
>= GreaterThanOrEqual(a: type; b: type): resultType; Сравнение
< LessThan(a: type; b: type): resultType; Сравнение
<= LessThanOrEqual(a: type; b: type): resultType; Сравнение
+ Add(a: type; b: type): resultType; Бинарный
- Subtract(a: type; b: type) : resultType; Бинарный
* Multiply(a: type; b: type) : resultType; Бинарный
/ Divide(a: type; b: type) : resultType; Бинарный
div IntDivide(a: type; b: type): resultType; Бинарный
mod Modulus(a: type; b: type): resultType; Бинарный
shl ShiftLeft(a: type; b: type): resultType; Бинарный
shr ShiftRight(a: type; b: type): resultType; Бинарный
and LogicalAnd(a: type; b: type): resultType; Бинарный
or LogicalOr(a: type; b: type): resultType; Бинарный
xor LogicalXor(a: type; b: type): resultType; Бинарный
and BitwiseAnd(a: type; b: type): resultType; Бинарный
or BitwiseOr(a: type; b: type): resultType; Бинарный
xor BitwiseXor(a: type; b: type): resultType; Бинарный

Атрибуты

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

Атрибут объявляется как обычный класс, наследник TCustomAttribute, например:

    type
       TCustomCodeAttribute = class(TCustomAttribute)
          private
              Fprop1 : integer;
              Fprop2 : integer;
              aVal   : integer;
              procedure Setprop1(p1 : integer);
              procedure Setprop2(p2 : integer);
          public
              constructor Create(const myVal : integer);
              property prop1 : integer read Fprop1 write Setprop1;
              property prop2 : integer read Fprop2 write Setprop2;
       end;

Конструктор атрибута будет в нашем примере выглядеть так:

  constructor TCustomCodeAttribute.Create(const myVal : integer);
  begin
      inherited Create;
      aVal := myVal;
  end;

А воспользоваться атрибутом можно следующим образом:

      [TCustomCodeAttribute(1024, prop1=512, prop2=128)]
      TMyClass = class(TObject)
      ...
      end;

Class helpers

Необходимость введения хелперов класса как элемента языка обусловлена желанием Borland перенести объектную библиотеку VCL на .NET. Как известно, в VCL базовым классом является TObject. В .NET ему соответствует класс Object. Однако класс Object хотя и является аналогом TObject, реализует далеко не все методы и свойства последнего. Многие классы из VCL так же имеют аналоги в .NET, частично реализующие функциональность VCL класса.

Конечно, можно было бы написать наследников .NET-классов, однако гораздо удобнее «подмешать» необходимую функциональность в .NET класс, не вникая в тонкости внутреннего устройства .NET класса. Именно этим и занимается хелпер. Если какой-либо член класса (свойство, метод, поле) не найден в основном классе, то делается попытка найти его в хелпере. Синтаксис объявления хелпера

type
  identifierName = class helper [(ancestor list)] for classTypeIdentifierName
    memberList
  end;

Продемонстрируем использование хелпера на простом примере:

type
   TMyClass = class
      procedure MyProc;
      function  MyFunc: Integer;
   end;
   ...
   procedure TMyClass.MyProc;
   var X: Integer;
   begin
      X := MyFunc;
   end;

   function TMyClass.MyFunc: Integer;
   begin
       ...
   end;
...
type 
   TMyClassHelper = class helper for TMyClass
     procedure HelloWorld;
     function MyFunc: Integer;
   end;
   ...
   procedure TMyClassHelper.HelloWorld;
   begin
      // Self относится к типу TMyClass, а не TMyClassHelper
      writeln(Self.ClassName);
   end;

   function TMyClassHelper.MyFunc: Integer;
   begin
     ... 
   end;
...
var 
  X: TMyClass;
begin
  X := TMyClass.Create;
  X.MyProc;    // Calls TMyClass.MyProc
  X.HelloWorld // Calls TMyClassHelper.HelloWorld
  X.MyFunc;    // Calls TMyClassHelper.MyFunc
end;

В данном примере объявляется класс TMyClass, содержащий процедуру MyProc и функцию MyFunc. Для класса TMyClass объявлен хелпер TMyClassHelper, содержащий процедуру HelloWorld и функцию MyFunc. Далее в коде создается экземпляр класса TMyClass и вызываются методы MyProc, HelloWorld, MyFunc. Процедура MyProc вызывается из класса, а два оставшихся метода из хелпера.

Объектная библиотека Delphi


Рисунок 6.

Фактически Delphi.NET имеет две объектные библиотеки: стандартную библиотеку классов .NET – FCL и перенесенную на платформу .NET VCL. Можно создавать приложения, используя одну из этих библиотек компонентов. Если с FCL более и менее все понятно, то о VCL.NET стоит рассказать подробнее.


Рисунок 7.

VCL.NET предоставляет тот же набор компонентов, что и старая добрая VCL. Borland приложила все усилия, чтобы старые проекты, написанные на Delphi легко переносились на платформу .NET. Пока рано говорить, насколько беспроблемно будет происходить перенос кода, однако при беглом взгляде глобальных проблем не видно. Помимо переноса старого кода приложений, Borland предусмотрела возможность импорта компонентов .NET в приложения VCL.NET. При этом создается обертка вокруг .NET-компонента, позволяющая использовать его в приложении VCL.NET.

Другие вкусности

Средства моделирования классов

Одним из очень удобных нововведений Delphi 8 является возможность визуализации диаграмм классов приложения.

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

Borland DB Providers

В составе Delphi, помимо стандартных провайдеров доступа к данным, входящих в состав .NET Framework, поставляются провайдеры от Borland, позволяющие работать с такими популярными серверами БД как:

Oracle

MS SQL

MS Access

Interbase

DB2

Общая архитектура доступа к данным в Delphi 8 показана на рисунке.


Рисунок 8.

Как видно из диаграммы, провайдеры от Borland (BDP – Borland Data Providers), работают с сервером напрямую, минуя OLE DB. Теоретически это позволяет повысить скорость работы, однако до тех пор, пока не будут проведены компетентные тесты, давать какие-то заключения преждевременно.

Заключение

За столь короткое время невозможно досконально изучить все нововведения, и данный обзор не претендует на исчерпывающую полноту. Однако мы постарались отметить большинство ключевых моментов, связанных с Delphi 8.

Несмотря на отдельные недостатки, новый продукт Borland производит приятное впечатление. По нашему мнению, Borland в очередной раз подтвердила свою репутацию одного из ведущих поставщиков средств разработки. Надеемся, что Delphi 8 займет достойное место среди инструментария разработки .NET приложений.

 


Copyright © 1994-2016 ООО "К-Пресс"