Object Pascal

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

Шаблон:Карточка языка программирования

Object Pascal (Шаблон:Tr-en) — язык программирования, разработанный в фирме Apple Computer в 1986 году группой Ларри Теслера, который консультировался с Никлаусом Виртом<ref>Шаблон:Cite journal</ref>. Произошёл от более ранней объектно-ориентированной версии Паскаль<ref>Буч Г. Объектно-ориентированное проектирование с примерами применения К.: Диалектика; М.: Конкорд, 1992. — 519 с.</ref>, называвшейся Clascal, который был доступен на компьютере Apple Lisa.

Изменения в Object Pascal от Borland в сравнении с Turbo Pascal

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

  • Фундаментальные (fundamental) типы. Их представление в памяти (число битов и наличие знака) строго фиксируется и выдерживается неизменным во всех последующих реализациях Object Pascal для любых операционных систем и компьютерных платформ.
  • Родовые (generic) типы. Их представление в памяти не фиксируется и будет реализовано оптимальным способом, в зависимости от реализации для конкретной операционной системы и компьютерной платформы.

Интерфейсы

См. Интерфейсы: Delphi

Перегрузка процедур и функций (не ООП)

Введена перегрузка процедур и функций, не являющихся членами объекта или класса. Перегружаются (с помощью ключевого слова overload) различающиеся типами и числом параметров процедуры и функции: <source lang="delphi" line="1"> procedure Calc(I: Integer); overload; // ... procedure Calc(S: String; J: Integer); overload; </source>

Динамический массив

Введён для устранения рутинных операций выделения и возвращения памяти в heap-область (кучу), и для того, чтобы избежать случайных ошибок и утечки памяти. Элементы массива должны быть одинаковыми по типу. Нумерация элементов начинается с нуля.

Пример объявления: <source lang="delphi" line="1"> var MyFlexibleArray: array of Real; </source>

Использование: <source lang="delphi" line="1"> var

 A, B: array of Integer;

begin

 SetLength(A, 1); //Выделяем память под один элемент
 A[0] := 1;   B := A;
 B[0] := 2;

end; </source>

Начиная с Delphi XE7 стали возможны следующие действия с динамическими массивами: <source lang="delphi" line="1"> var M: array of integer; begin

 M := [1, 2, 3, 4, 5];

end;

M := M + [5, 6, 7];
Insert([6, 7, 8], M, 5); // вставка массива [6, 7, 8], в M, начиная с индекса 5
Delete(M, 1, 3); // удаляем 3 элемента, начиная с индекса 1
Concat([1, 2, 3, 4], [5, 6, 7])

</source> То есть с динамическими массивами можно работать так же, как со строками.

В динамическом массиве также возможно задание открытого массива параметров, но тип их должен быть объявлен ранее, например: <source lang="delphi" line="1"> type TDynamicCharArray = array of Char; function Find(A: TDynamicCharArray): Integer; </source>

Динамическая типизация

Операторы динамической проверки и приведения типов

В языке Object Pascal фирмы Borland появилась динамическая типизация, а также оператор динамического приведения типов as и оператор is для динамической проверки типов. Также в открытом массиве параметров стала возможна передача параметров различного типа (variant open array parameters).

Вариантный тип

В языке Object Pascal был введён вариантный тип данных (Variant), тип которых не известен на этапе компиляции и может изменяться на этапе выполнения программы. Однако этот тип данных поглощает больше памяти по сравнению с соответствующими переменными и операции над данными типа Variant выполняются медленнее. Более того, недопустимые операции над данными этого типа чаще приводят к ошибкам на этапе выполнения программы, в то время как подобные ошибки над данными другого типа были бы выявлены ещё на этапе компиляции.

Вариантные переменные могут принимать различные значения (целые, строковые, булевские, Currency, OLE-строки), быть массивами элементов этих же типов и массивом значений вариантного типа, а также содержать COM и CORBA объекты, чьи методы и свойства могут быть доступны посредством этого типа. Однако Variant не может содержать:

  • данные структурных типов;
  • указатели;
  • Int64 (начиная с Delphi 6 — может).

Variant можно смешивать (в выражениях и операторах) с другими вариантами, числовыми, строковыми и булевскими данными. При этом компилятор автоматически выполняет преобразование типа. Варианты, содержащие строки, не могут, однако, индексироваться (V[i] недопустимо). <source lang="delphi" line="1"> var

 V1, V2, V3, V4, V5: Variant;
 I: Integer;
 D: Double;
 S: String;

begin

 V1 := 1; //значение типа integer
 V2 := 359.768; //значение типа real
 V3 := 'Hello world!'; //значение типа string

end; </source>

Параметры типа вариантного открытого массива

Стала возможна передача параметров различного типа. В оригинале он назван как «variant open array parameters». Тип данных определяется динамически в процессе выполнения программы. Так же как и в обычном открытом массиве функция High вызывается для определения числа элементов массива. Для объявления используются ключевые слова array of const. Пример: <source lang="delphi" line="1"> function Output(const Args: array of const): string; var

 I: Integer;

begin

 Result := ;
 for I := 0 to High(Args) do with Args[I] do
   case VType of
     vtString:     Result := Result + VString^;
     vtPChar:      Result := Result + VPChar;
     vtInteger:    Result := Result + IntToStr(VInteger);
     vtBoolean:    Result := Result + BoolToStr(VBoolean);
     vtChar:       Result := Result + VChar;
     vtExtended:   Result := Result + FloatToStr(VExtended^);
     vtObject:     Result := Result + VObject.ClassName;
     vtClass:      Result := Result + VClass.ClassName;
     vtVariant:    Result := Result + string(VVariant^);
     vtInt64:      Result := Result + IntToStr(VInt64^);
     vtAnsiString: Result := Result + string(VAnsiString);
     vtCurrency:   Result := Result + CurrToStr(VCurrency^);
   end;
 Result := Result + ' ';

end; //...

Output(['test', 777, '@', True, 3.14159, TForm]); //передача открытого массива параметров </source>

Будет возвращена строка «test 777 @ T 3.14159 TForm».

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

Различия в объектных моделях

Для введения новой объектной модели введено ключевое слово classTurbo Pascal ключевое слово object).

Введены операторы для проверки и приведения классов is и as динамически в ходе выполнения программы. Появились указатели на методы, для чего введено новое использование ключевого слова object: <source lang="delphi" line="1"> type

 TMyMethod = procedure (Sender : Object) of object;

</source>

Изменения синтаксиса из-за изменения размещения объектов

В Turbo Pascal можно было работать как с динамическими, так и со статическими экземплярами объектов.

В объектной модели Object Pascal программист работает только с динамическими экземплярами классов, выделяемых в heap-области (куче). В связи с этим изменён синтаксис обращения к полям и методам объектов.

Ранее для работы с динамическими экземплярами объектов, инициализированными с использованием обращения к конструктору в сочетании с функцией New, необходимо было использовать обращение по указателю (^). Теперь тип класса стал являться по умолчанию также указателем.

Пример для сравнения:

Объектная модель в Turbo Pascal: <source lang="pascal" line="1"> type

 PMyObject = ^TMyObject;
 TMyObject = object (TObject)
   MyField : PMyType;
   constructor Init;
 end;

//... var

 MyObject : PMyObject;

begin

 MyObject := New(PMyObject,Init);
 MyObject^.MyField := //...

end; </source>

Новая объектная модель в Object Pascal: <source lang="delphi" line="1"> type

 TMyObject = class (TObject)
   MyField : TMyType;
   constructor Create;
 end;

//... var

 MyObject : TMyObject;

begin

 MyObject := TMyObject.Create;
 MyObject.MyField := //...

end; </source>

Было изменено соглашение об именовании конструкторов и деструкторов. В старой объектной модели вызов New отвечал за распределение памяти, а обращение к конструктору инициализировало выделенную область памяти. В новой модели эти действия выполняет конструктор Create. Начиная с версии Delphi XE появились статические методы класса.<ref>Преимущества перехода на Delphi XE Что нового по сравнению с Delphi 7 Андреано Лануш (Andreano Lanusse) Шаблон:Wayback,Ноябрь 2010 г. Embarcadero Technologies Россия, СНГ</ref>

Появилась возможность ограничивать видимость членов класса (методы, свойства), которые предназначены для использования только в реализации производных классов. Это даёт возможность защищать исходный код от модификации пользователями класса. Такие методы содержатся в секции protected (защищённые) в объявлении класса.

Визуальное объектно-ориентированное программирование

Появились понятия свойства (property) и связанные со свойствами ключевые слова read, write, stored, default (nodefault), index. Свойства визуальных объектов, видимых в интегрированной среде разработки, объявляются с помощью нового слова published в качестве секции в объявлении класса, являющегося визуальным объектом.

<source lang="delphi" line="1"> type

 {объявление}
 generic TList<T> = class
   Items: array of T;
   procedure Add(Value: T);
 end;

implementation

 {реализация}
 procedure TList.Add(Value: T);
 begin
   SetLength(Items, Length(Items) + 1);
   Items[Length(Items) - 1] := Value;
 end;

</source>

Общий класс может быть просто специализирован для конкретного типа с использованием ключевого слова specialize: <source lang="delphi" line="1"> type

 TIntegerList = specialize TList<Integer>;
 TPointerList = specialize TList<Pointer>;
 TStringList  = specialize TList<string>;

</source>

Разработчики TMT Pascal (модификация Object Pascal) первыми ввели полноценную перегрузку операторов, что впоследствии было перенято разработчиками других диалектов языка: Delphi (с Delphi 2005), Free Pascal и др.

Пример: <source lang="delphi" line="1"> {объявление} type

 TVector = packed record
   A, B, C: Double;
   procedure From(const A, B, C: Double);
   class operator Add(const Left, Right: TVector): TVector;
   class operator Implicit(const v: TVector): TPoint;
 end;

{реализация} implementation //...

 class operator TVector.Add(const Left, Right: TVector): TVector;
 begin
   Result.A := Left.A + Right.A;
   Result.B := Left.B + Right.B;
   Result.C := Left.C + Right.C;
 end;
 class operator TVector.Implicit(const v: TVector): TPoint;
 begin
   Result.A := round(v.A);
   Result.B := round(v.B);
 end;

//...

{использование} var

 v1, v2: TVector;

begin

 v1.From(20, 70, 0);
 v2.From(15, 40, 4);
 Canvas.Polygon([v1, v2, v1 + v2]);

end; </source>

Поддержка различными разработчиками

Начиная с версии среды Delphi 7 фирма Borland стала официально называть язык Object Pascal как Delphi<ref>Delphi Language OverviewШаблон:Недоступная ссылка</ref>.

Язык Object Pascal поддерживается и развивается другими разработчиками. Наиболее серьёзные реализации Object Pascal (помимо Delphi) — это кроссплатформенный TopSpeed Pascal (версия языка Turbo Pascal<ref>TopSpeed-компиляторы: не дожили до триумфа Шаблон:Webarchive</ref>) мультиязыковой среды TopSpeed, TMT Pascal, Virtual Pascal, PascalABC.NET, Free Pascal, GNU Pascal. Язык программирования Oxygene является диалектом Object Pascal для платформы .NET и дальнейшим его развитием, а новыми возможностями языка является оператор ":", асинхронный и отложенный вызовы методов, асинхронное выполнение блока кода, параллельные циклы, анонимные конструкторы, элементы контрактного и аспектно-ориентированного программирования и др.<ref>Шаблон:Cite web</ref> (компилятор распространяется без ограничений).

Примеры «Hello, world!» в различных объектных расширениях языка

Шаблон:Начало скрытого блока <source lang="pascal"> program ObjectPascalExample;

type

 THelloWorld = object
   procedure Put;
 end;

var

 HelloWorld: THelloWorld;

procedure THelloWorld.Put; begin

 WriteLn('Hello, World!');

end;

begin

 New(HelloWorld);
 HelloWorld.Put;
 Dispose(HelloWorld);

end. </source> Шаблон:Конец скрытого блока

Шаблон:Начало скрытого блока Delphi (для обеспечения обратной совместимости) и Free Pascal также поддерживают этот вариант синтаксиса. <source lang="pascal"> program ObjectPascalExample;

type

 PHelloWorld = ^THelloWorld;
 THelloWorld = object
   procedure Put;
 end;

var

 HelloWorld: PHelloWorld; { это указатель на THelloWorld }

procedure THelloWorld.Put; begin

 WriteLn('Hello, World!');

end;

begin

  New(HelloWorld);
  HelloWorld^.Put;
  Dispose(HelloWorld);

end. </source> Шаблон:Конец скрытого блока Шаблон:Начало скрытого блока В Free Pascal этот вариант синтаксиса доступен в режимах ObjFpc и Delphi.<ref>Шаблон:Cite web</ref>

<source lang="delphi"> program ObjectPascalExample;

type

 THelloWorld = class                    { определение класса }
   procedure Put;
 end;

procedure THelloWorld.Put; { описание процедуры метода Put класса THelloWorld } begin

 Writeln('Hello, World!');

end;

var

 HelloWorld: THelloWorld;               { определение переменной-указателя на экземпляр класса }

begin

 HelloWorld := THelloWorld.Create;      { конструктор возвращает значение указателя на экземпляр класса }
 HelloWorld.Put;
 HelloWorld.Free;                       { деструктор уничтожает экземпляр класса и освобождает область памяти }

end. </source> Шаблон:Конец скрытого блока

Примечания

Шаблон:Примечания

Шаблон:Pascal