Object Pascal: различия между версиями

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску
[непроверенная версия][непроверенная версия]
Содержимое удалено Содержимое добавлено
 
(не показано 40 промежуточных версий 24 участников)
Строка 1: Строка 1:
{{Карточка языка программирования
{{Карточка языка программирования
|name = Object Pascal
|logo =
|semantics = [[Императивное программирование|императивная]]
|paradigm = [[Мультипарадигмальный язык программирования|мультипарадигмальный]]: <br />[[Императивный язык программирования|императивный]], [[Структурное программирование|структурный]], [[Объектно-ориентированный язык программирования|объектно-ориентированный]], [[Обобщённое программирование|обобщённый]]<ref>[http://hallvards.blogspot.com/2007/08/highlander2-beta-generics-in-delphi-for.html Hallvard’s Blog: Highlander2 Beta: Generics in Delphi for .NET<!-- Заголовок добавлен ботом -->]</ref>, [[Процедурный язык программирования|процедурный]]
|class = [[Компилятор|компилируемый]]
|class = [[Компилятор|компилируемый]]
|year = 1986
|designer = [[Ларри Теслер]], [[Никлаус Вирт]]
|extension =
|latest_release_version =
|latest_release_date =
|latest_preview_version =
|latest_preview_date =
|typing = [[Статическая типизация|статическая]], [[динамическая типизация|динамическая]] (array of const, [[RTTI]], Variant), [[Строгая типизация|строгая]]
|typing = [[Статическая типизация|статическая]], [[динамическая типизация|динамическая]] (array of const, [[RTTI]], Variant), [[Строгая типизация|строгая]]
|implementations = [[Delphi (язык программирования)|Delphi]] ([[x86]] and [[Common Language Infrastructure|CLI]]), [[Oxygene (язык программирования)|Oxygene]] ([[Common Language Infrastructure|CLI]]), [[Free Pascal]] ([[x86]], [[x86-64]], [[PowerPC]], [[ppc64]], [[SPARC]] and [[ARM (архитектура)|ARM]]), [[Virtual Pascal]] ([[x86]]), [[TMT Pascal]] ([[x86]]), Turbo51 ([[Intel 8051]])
|implementations = [[Delphi (язык программирования)|Delphi]] ([[x86]] and [[Common Language Infrastructure|CLI]]), [[Oxygene (язык программирования)|Oxygene]] ([[Common Language Infrastructure|CLI]]), [[Free Pascal]] ([[x86]], [[x86-64]], [[PowerPC]], [[ppc64]], [[SPARC]] and [[ARM (архитектура)|ARM]]), [[Virtual Pascal]] ([[x86]]), [[TMT Pascal]] ([[x86]]), Turbo51 ([[Intel 8051]])
|dialects = Apple, [[Turbo Pascal]], objfpc, [[Delphi (язык программирования)|Delphi]], Delphi.NET, [[Oxygene (язык программирования)|Oxygene]]
|dialects = Apple, [[Turbo Pascal]], objfpc, [[Delphi (язык программирования)|Delphi]], Delphi.NET, [[Oxygene (язык программирования)|Oxygene]]
|influenced_by = [[Паскаль (язык программирования)|Паскаль]], [[Smalltalk]]
|influenced = [[C Sharp|C#]], [[Java]], [[Nim]]
|influenced = [[C Sharp|C#]], [[Java]]
|license =
|website =
|extension = .p .pp .pas
}}
}}


'''Object Pascal''' ('''Объектный Паскаль''') — [[язык программирования]], разработанный в фирме [[Apple Computer]] в [[1986 год]]у группой [[Ларри Теслер]]а, который консультировался с [[Никлаус Вирт|Никлаусом Виртом]]. Произошёл от более ранней объектно-ориентированной версии [[Паскаль (язык программирования)|Паскаль]]<ref>Буч Г. Объектно-ориентированное проектирование с примерами решения[itbookz.ifolder.ru/7276278]</ref>, называвшейся [[Clascal]], который был доступен на компьютере [[Apple Lisa]].
'''Object Pascal''' ({{tr-en|Объектный Паскаль}}) — [[язык программирования]], разработанный в фирме [[Apple Computer]] в [[1986 год]]у группой [[Ларри Теслер]]а, который консультировался с [[Никлаус Вирт|Никлаусом Виртом]]<ref>{{cite journal |last1=Tesler |first1=Larry |title=Object Pascal Report |journal=Structured Language World |date=1985 |volume=9 |issue=3 |pages=10–7}}</ref>. Произошёл от более ранней объектно-ориентированной версии [[Паскаль (язык программирования)|Паскаль]]<ref>Буч Г. Объектно-ориентированное проектирование с примерами применения К.: Диалектика; М.: Конкорд, 1992. — 519 с.</ref>, называвшейся [[Clascal]], который был доступен на компьютере [[Apple Lisa]].


== Изменения в Object Pascal от [[Borland]] в сравнении с [[Turbo Pascal]] ==
== Примеры Hello World! в различных объектных расширениях языка ==
Изменения коснулись групп целых, символьных и строковых типов, которые стали разделяться на две категории:
=== Object Pascal от Apple ===
* '''Фундаментальные (fundamental) типы'''. Их представление в памяти (число битов и наличие знака) строго фиксируется и выдерживается неизменным во всех последующих реализациях Object Pascal для любых операционных систем и компьютерных платформ.
<source lang="pascal">
* '''Родовые (generic) типы'''. Их представление в памяти не фиксируется и будет реализовано оптимальным способом, в зависимости от реализации для конкретной операционной системы и компьютерной платформы.
program ObjectPascalExample;


=== Интерфейсы ===
type
См. [[Интерфейс (ООП)#Delphi|Интерфейсы: Delphi]]
THelloWorld = object
procedure Put;
end;


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


=== Динамический массив ===
procedure THelloWorld.Put;
Введён для устранения рутинных операций выделения и возвращения памяти в heap-область (кучу), и для того, чтобы избежать случайных ошибок и утечки памяти. Элементы массива должны быть одинаковыми по типу. Нумерация элементов начинается с нуля.
begin
WriteLn('Hello, World!');
end;


Пример объявления:
begin
<source lang="delphi">
New(HelloWorld);
var MyFlexibleArray: array of Real;
HelloWorld.Put;
Dispose(HelloWorld);
end.
</source>
</source>


Использование:
=== Turbo Pascal ===
<source lang="delphi">
''Delphi и Freepascal также поддерживают этот вариант синтаксиса. В Delphi для обеспечения обратной совместимости, для Freepascal — это синтаксис по умолчанию''
var
<source lang="pascal">
A, B: array of Integer;
program ObjectPascalExample;

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

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

procedure THelloWorld.Put;
begin
WriteLn('Hello, World!');
end;

begin
begin
SetLength(A, 1); //Выделяем память под один элемент
New(HelloWorld);
A[0] := 1; B := A;
HelloWorld^.Put;
B[0] := 2;
Dispose(HelloWorld);
end.
end;
</source>
</source>


Начиная с Delphi XE7 стали возможны следующие действия с динамическими массивами:
=== Object Pascal в Delphi и Free Pascal ===
<source lang="delphi">
''В Free Pascal этот вариант синтаксиса доступен в режимах ObjFpc и Delphi''<ref>{{cite web|url=http://www.freepascal.org/docs-html/ref/refch6.html#x66-760006|title=Chapter 6: Classes|author=Michaël Van Canneyt|date=декабрь 2011|work=Free Pascal : Reference guide.|lang=en|accessdate=2012-01-16|archiveurl=http://www.webcitation.org/659qF0xXI|archivedate=2012-02-02}}</ref>
var M: array of integer;
<source lang="pascal">
program ObjectPascalExample;

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

procedure THelloWorld.Put; { описание процедуры метода Put класса THelloWorld }
begin
begin
M := [1, 2, 3, 4, 5];
Writeln('Hello, World!');
end;
end;


M := M + [5, 6, 7];
var
Insert([6, 7, 8], M, 5); // вставка массива [6, 7, 8], в M, начиная с индекса 5
HelloWorld: THelloWorld; { определение переменной-указателя на экземпляр класса }
Delete(M, 1, 3); // удаляем 3 элемента, начиная с индекса 1

Concat([1, 2, 3, 4], [5, 6, 7])
begin
HelloWorld := THelloWorld.Create; { конструктор возвращает значение указателя на экземпляр класса }
HelloWorld.Put;
HelloWorld.Free; { деструктор уничтожает экземпляр класса и освобождает область памяти }
end.
</source>
</source>
То есть с динамическими массивами можно работать так же, как со строками.


В динамическом массиве также возможно задание открытого массива параметров, но тип их должен быть объявлен ранее, например:
== Изменения в Object Pascal от Borland в сравнении с [[Turbo Pascal]] ==
<source lang="delphi">

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

=== Интерфейсы ===
См. [[Интерфейс (ООП)#Delphi|Интерфейсы: Delphi]]

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

=== Динамический массив ===
Введен для устранения рутинных операций выделения и возвращения памяти в heap-область (кучу), и для того, чтобы избежать случайных ошибок и утечки памяти. Элементы массива должны быть одинаковыми. Нумерация элементов начинается с нуля.<br />
Пример объявления:

var MyFlexibleArray: '''array of''' Real;<br />
Использование:

var<br />
A, B: '''array of''' Integer;
begin
'''SetLength'''(A, 1); {специальная процедура выделения памяти}
A[0] := 1;
B := A;
B[0] := 2;
end;
В динамическом массиве тоже возможно задание открытого массива параметров, но тип их должен быть объявлен ранее, например:<br />
'''type''' TDynamicCharArray = '''array of''' Char;<br />
function Find(A: TDynamicCharArray): Integer;
function Find(A: TDynamicCharArray): Integer;
</source>


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

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


==== Вариантный тип ====
==== Вариантный тип ====
В языке Object Pascal был введен вариантный тип данных ('''Variant'''), тип которых не известен на этапе компиляции и может изменяться на этапе выполнения программы.
В языке Object Pascal был введён вариантный тип данных ('''Variant'''), тип которых не известен на этапе компиляции и может изменяться на этапе выполнения программы.
Однако этот тип данных поглощает больше памяти по сравнению с соответствующими переменными и операции над данными типа Variant выполняются медленнее.
Однако этот тип данных поглощает больше памяти по сравнению с соответствующими переменными и операции над данными типа Variant выполняются медленнее.
Более того, недопустимые операции над данными этого типа чаще приводят к ошибкам на этапе выполнения программы, в то время как подобные ошибки над данными другого типа были бы выявлены ещё на этапе компиляции.
Более того, недопустимые операции над данными этого типа чаще приводят к ошибкам на этапе выполнения программы, в то время как подобные ошибки над данными другого типа были бы выявлены ещё на этапе компиляции.
Строка 149: Строка 80:
* Int64 (начиная с Delphi 6 — может).
* Int64 (начиная с Delphi 6 — может).


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

V1, V2, V3, V4, V5: Variant;
var
I: Integer;
V1, V2, V3, V4, V5: '''Variant''';
I: Integer;
D: Double;
D: Double;
S: String;
begin
S: string;
V1 := 1; //значение типа integer
begin
V1 := 1; { значение типа integer }
V2 := 359.768; //значение типа real
V2 := 359.768; { значение типа real }
V3 := 'Hello world!'; //значение типа string
end;
V3 := 'Hello world!'; { значение типа string }
</source>
...


==== Параметры типа вариантного открытого массива ====
==== Параметры типа вариантного открытого массива ====
Стала возможна передача параметров различного типа.
Стала возможна передача параметров различного типа.
В оригинале он назван как «variant open array parameters». Тип данных определяется динамически в процессе выполнения программы. Так же как и в обычном открытом массиве функция High вызывается для определения числа элементов массива. Для объявления используются ключевые слова ''' array of const'''.
В оригинале он назван как «variant open array parameters». Тип данных определяется динамически в процессе выполнения программы. Так же как и в обычном открытом массиве функция High вызывается для определения числа элементов массива. Для объявления используются ключевые слова '''array of const'''. Пример:
<source lang="delphi">
Пример:
function Output(const Args:''' array of const'''): string;
function Output(const Args: array of const): string;
var
var
I: Integer;
I: Integer;
begin
begin
Result := '';
Result := '';
for I := 0 to '''High'''(Args) do with Args[I] do
for I := 0 to High(Args) do with Args[I] do
case VType of
case VType of
vtString: Result := Result + VString^;
vtString: Result := Result + VString^;
vtPChar: Result := Result + VPChar;
vtPChar: Result := Result + VPChar;
vtInteger: Result := Result + IntToStr(VInteger);
vtInteger: Result := Result + IntToStr(VInteger);
vtBoolean: Result := Result + BoolToStr(VBoolean);
vtBoolean: Result := Result + BoolToStr(VBoolean);
vtChar: Result := Result + VChar;
vtChar: Result := Result + VChar;
vtExtended: Result := Result + FloatToStr(VExtended^);
vtExtended: Result := Result + FloatToStr(VExtended^);
vtObject: Result := Result + VObject.ClassName;
vtObject: Result := Result + VObject.ClassName;
vtClass: Result := Result + VClass.ClassName;
vtClass: Result := Result + VClass.ClassName;
vtVariant: Result := Result + string(VVariant^);
vtVariant: Result := Result + string(VVariant^);
vtInt64: Result := Result + IntToStr(VInt64^);
vtInt64: Result := Result + IntToStr(VInt64^);
vtAnsiString: Result := Result + string(VAnsiString);
vtAnsiString: Result := Result + string(VAnsiString);
vtCurrency: Result := Result + CurrToStr(VCurrency^);
vtCurrency: Result := Result + CurrToStr(VCurrency^);
end;
end;
Result:=Result+ ' ';
end;
...
Output(['test', 777, '@', True, 3.14159, TForm]) {передача открытого массива параметров}
будет возвращена строка: «test 777 @ T 3.14159 TForm».


Result := Result + ' ';
Как видно, имеет свою внутреннюю структуру, обращение к которой дает возможность определить тип данных. В строке вызова функции создается массив, с помощью ''конструктора открытого массива'', который использует квадратные скобки.
end;
//...

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

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

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


=== Различия в объектных моделях ===
=== Различия в объектных моделях ===
Строка 199: Строка 134:


Введены операторы для проверки и приведения классов '''is''' и '''as''' динамически в ходе выполнения программы.
Введены операторы для проверки и приведения классов '''is''' и '''as''' динамически в ходе выполнения программы.
Появились указатели на методы, для чего введено новое использование ключевого слова '''object''':<br />
Появились указатели на методы, для чего введено новое использование ключевого слова '''object''':
<source lang="delphi">
'''type'''<br />
type
   TMyMethod = '''procedure''' (Sender : Object) '''of object''';
TMyMethod = procedure (Sender : Object) of object;
</source>


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

В объектной модели Object Pascal программист работает только с динамическими экземплярами классов, выделяемых в heap-области (куче). В связи с этим изменен синтаксис обращения к полям и методам объектов.
В объектной модели Object Pascal программист работает только с динамическими экземплярами классов, выделяемых в heap-области (куче). В связи с этим изменён синтаксис обращения к полям и методам объектов.
Ранее для работы с динамическими экземплярами объектов, проинициализированными с использованием обращения к конструктору в сочетании с функцией '''New''', необходимо было использовать обращение «по адресу» (^). Теперь тип класса стал являться по умолчанию также указателем.<br />

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

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


;Объектная модель в Turbo Pascal (выделены участки кода, подвергшиеся изменению)
'''Объектная модель в Turbo Pascal''':
<source lang="pascal">
type
type
PMyObject = '''^TMyObject''';
PMyObject = ^TMyObject;
TMyObject = '''object''' (TObject)
TMyObject = object (TObject)
MyField : PMyType;
MyField : PMyType;
constructor Init;
constructor Init;
end;
end;
...
//...
'''var'''
var
MyObject : PMyObject;
MyObject : PMyObject;
begin
begin
MyObject:='''New'''(PMyObject,Init);
MyObject^.MyField:= ...
MyObject := New(PMyObject,Init);
MyObject^.MyField := //...
end;
end;
</source>


;Новая объектная модель в Object Pascal
'''Новая объектная модель в Object Pascal''':
<source lang="delphi">
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>[http://www.interface.ru/iarticle/files/25458_53867033.pdf Преимущества перехода на Delphi XE Что нового по сравнению с Delphi 7 Андреано Лануш (Andreano Lanusse)] {{Wayback|url=http://www.interface.ru/iarticle/files/25458_53867033.pdf |date=20160615174245 }},Ноябрь 2010 г. Embarcadero Technologies Россия, СНГ</ref>
type
TMyObject = '''class''' (TObject)
MyField : TMyType;
constructor Create;
end;
...
var
MyObject : '''TMyObject''';
begin
MyObject:='''TMyObject.Create''';
MyObject.MyField:= ...
end;
С помощью точки стало возможным обращаться для доступа к методам '''класса'''. Кроме того, было изменено соглашение об именовании конструкторов и деструкторов. В старой объектной модели вызов '''New''' отвечал за распределение памяти, а обращение к конструктору инициализировало выделенную область памяти. В новой модели эти действия выполняет конструктор '''Create'''.


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


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


=== [[Обобщенное программирование|Обобщения]] ===
=== [[Обобщённое программирование|Обобщения]] ===
<source lang="delphi">
'''type'''
type
'''generic''' TList<T> = '''class''' {объявление}
{объявление}
generic TList<T> = class
Items: array of T;
Items: array of T;
procedure Add(Value: T);
procedure Add(Value: T);
end;
end;

Implementation
implementation
{реализация}
{реализация}
procedure TList.Add(Value: T);
procedure TList.Add(Value: T);
begin
begin
SetLength(Items, Length(Items) + 1);
Items[Length(Items) - 1] := Value;
SetLength(Items, Length(Items) + 1);
Items[Length(Items) - 1] := Value;
end;
end;
Общий класс может быть просто специализирован для конкретного типа с использованием ключевого слова '''specialize:'''
</source>
Typ

TIntegerList = '''specialize''' TList<Integer>;
Общий класс может быть просто специализирован для конкретного типа с использованием ключевого слова '''specialize''':
TPointerList = '''specialize''' TList<Pointer>;
<source lang="delphi">
TStringList = '''specialize''' TList<string>;
type
TIntegerList = specialize TList<Integer>;
TPointerList = specialize TList<Pointer>;
TStringList = specialize TList<string>;
</source>


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

Пример:
Пример:
<source lang="delphi">
{объявление}
{объявление}
type
type
TVector = packed record
TVector = packed record
A, B, C: Double;
procedure From(const A, B, C: Double);
A, B, C: Double;
procedure From(const A, B, C: Double);
'''class operator''' Add(const Left, Right: TVector): TVector;
class operator Add(const Left, Right: TVector): TVector;
'''class operator''' Implicit(const v: TVector): TPoint;
class operator Implicit(const v: TVector): TPoint;
end;
end;

implementation
{реализация}
...
implementation
{реализация}
//...
'''class operator '''TVector.Add(const Left, Right: TVector): TVector;
class operator TVector.Add(const Left, Right: TVector): TVector;
begin
begin
Result.A := Left.A + Right.A;
Result.B := Left.B + Right.B;
Result.A := Left.A + Right.A;
Result.C := Left.C + Right.C;
Result.B := Left.B + Right.B;
Result.C := Left.C + Right.C;
end;<br />
end;
'''class operator''' TVector.Implicit(const v: TVector): TPoint;

begin
class operator TVector.Implicit(const v: TVector): TPoint;
Result.A := round(v.A);
begin
Result.B := round(v.B);
Result.A := round(v.A);
end;<br />
Result.B := round(v.B);
...
end;
{использование:}
//...
var

{использование}
var
v1, v2: TVector;
v1, v2: TVector;
begin
begin
v1.From(20, 70, 0);
v1.From(20, 70, 0);
v2.From(15, 40, 4);
v2.From(15, 40, 4);
Canvas.Polygon([v1, v2, v1 + v2]);
Canvas.Polygon([v1, v2, v1 + v2]);
end;
end;
</source>


== Поддержка различными разработчиками ==
== Поддержка различными разработчиками ==
Начиная с версии среды Delphi 7, фирма [[Borland]] стала официально называть язык Object Pascal как [[Delphi (язык программирования)|Delphi]]<ref>[http://docs.codegear.com/docs/radstudio/radstudio2007/RS2007_helpupdates/HUpdate4/EN/html/devcommon/overview_xml.html Delphi Language Overview]</ref>.
Начиная с версии среды Delphi 7, фирма [[Borland]] стала официально называть язык Object Pascal как [[Delphi (язык программирования)|Delphi]]<ref>[http://docs.codegear.com/docs/radstudio/radstudio2007/RS2007_helpupdates/HUpdate4/EN/html/devcommon/overview_xml.html Delphi Language Overview]{{Недоступная ссылка|date=2018-01|bot=InternetArchiveBot }}</ref>.


Язык Object Pascal поддерживается и развивается другими разработчиками. Наиболее серьёзные реализации Object Pascal (помимо Delphi) — это кроссплатформенный [[TopSpeed Pascal]] (версия языка Turbo Pascal<ref>[http://www.nf-team.org/drmad/stuff/t.htm TopSpeed-компиляторы: не дожили до триумфа]</ref>) мультиязыковой среды [[JPI#TopSpeed JPI|TopSpeed]], [[TMT Pascal]], [[Virtual Pascal]], [[PascalABC.NET]], [[Free Pascal]], [[GNU Pascal]]. На Object Pascal основан язык программирования [[Oxygene (язык программирования)|Oxygene]].
Язык Object Pascal поддерживается и развивается другими разработчиками. Наиболее серьёзные реализации Object Pascal (помимо Delphi) — это кроссплатформенный [[TopSpeed Pascal]] (версия языка Turbo Pascal<ref>[http://www.nf-team.org/drmad/stuff/t.htm TopSpeed-компиляторы: не дожили до триумфа] {{webarchive|url=https://web.archive.org/web/20120111161303/http://www.nf-team.org/drmad/stuff/t.htm |date=2012-01-11 }}</ref>) мультиязыковой среды [[JPI#TopSpeed JPI|TopSpeed]], [[TMT Pascal]], [[Virtual Pascal]], [[PascalABC.NET]], [[Free Pascal]], [[GNU Pascal]]. Язык программирования [[Oxygene (язык программирования)|Oxygene]] является диалектом Object Pascal для платформы .NET и дальнейшим его развитием, а новыми возможностями языка является оператор ":", асинхронный и отложенный вызовы методов, асинхронное выполнение блока кода, параллельные циклы, анонимные конструкторы, элементы контрактного и аспектно-ориентированного программирования и др.<ref>{{Cite web |url=https://codmasters.ru/thread-33-1-1.html |title=Remobjects Oxygene |accessdate=2015-11-16 |archiveurl=https://web.archive.org/web/20151117021059/https://codmasters.ru/thread-33-1-1.html |archivedate=2015-11-17 |deadlink=yes }}</ref> (компилятор распространяется без ограничений).

== Примеры «[[Hello, world!]]» в различных объектных расширениях языка ==
{{Начало скрытого блока|Заголовок=Object Pascal от Apple}}
<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>
{{Конец скрытого блока}}

{{Начало скрытого блока|Заголовок=Turbo Pascal}}
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>
{{Конец скрытого блока}}
{{Начало скрытого блока|Заголовок=Delphi и Free Pascal}}
В Free Pascal этот вариант синтаксиса доступен в режимах '''ObjFpc''' и '''Delphi'''.<ref>{{cite web|url=http://www.freepascal.org/docs-html/ref/refch6.html#x66-760006|title=Chapter 6: Classes|author=Michaël Van Canneyt|date=2011-12|work=Free Pascal : Reference guide.|lang=en|accessdate=2012-01-16|archiveurl=https://www.webcitation.org/659qF0xXI?url=http://www.freepascal.org/docs-html/ref/refch6.html#x66-760006|archivedate=2012-02-02|deadurl=yes}}</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>
{{Конец скрытого блока}}


== Примечания ==
== Примечания ==
{{примечания}}
{{примечания}}


{{rq|sources|refless}}
{{Pascal}}
{{Pascal}}
{{Языки программирования}}

[[Категория:Семейство языков программирования Pascal]]
[[Категория:Delphi]]


[[Категория:Object Pascal]]
[[ar:أوبجكت باسكال]]
[[cs:Object Pascal]]
[[da:Object Pascal]]
[[de:Object Pascal]]
[[en:Object Pascal]]
[[eo:Objektema Paskalo]]
[[es:Object Pascal]]
[[fi:Object Pascal]]
[[fr:Object Pascal]]
[[ja:Object Pascal]]
[[ko:오브젝트 파스칼]]
[[ms:Object Pascal]]
[[nl:Object Pascal]]
[[pl:Object Pascal]]
[[pt:Object Pascal]]
[[ro:Object Pascal]]
[[sk:Object Pascal]]
[[sq:Object Pascal]]
[[sv:Object Pascal]]
[[tg:Object Pascal]]
[[th:ภาษาอ็อบเจกต์ปาสกาล]]
[[tr:Object Pascal]]
[[uk:Object Pascal]]
[[zh:Object Pascal]]

Текущая версия от 12:44, 17 июля 2024

Object Pascal
Класс языка объектно-ориентированный, мультипарадигмальный, императивный, структурный язык программирования[вд] и язык программирования
Тип исполнения компилируемый
Появился в 1986
Разработчик Ларри Теслер и Никлаус Вирт
Расширение файлов .p, .pp или .pas
Система типов статическая, динамическая (array of const, RTTI, Variant), строгая
Основные реализации Delphi (x86 and CLI), Oxygene (CLI), Free Pascal (x86, x86-64, PowerPC, ppc64, SPARC and ARM), Virtual Pascal (x86), TMT Pascal (x86), Turbo51 (Intel 8051)
Диалекты Apple, Turbo Pascal, objfpc, Delphi, Delphi.NET, Oxygene
Испытал влияние Паскаль и Smalltalk
Повлиял на C#, Java, Nim
Логотип Викисклада Медиафайлы на Викискладе

Object Pascal (с англ. — «Объектный Паскаль») — язык программирования, разработанный в фирме Apple Computer в 1986 году группой Ларри Теслера, который консультировался с Никлаусом Виртом[1]. Произошёл от более ранней объектно-ориентированной версии Паскаль[2], называвшейся Clascal, который был доступен на компьютере Apple Lisa.

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

[править | править код]

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

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

Интерфейсы

[править | править код]

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

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

[править | править код]

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

procedure Calc(I: Integer); overload;
// ...
procedure Calc(S: String; J: Integer); overload;

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

[править | править код]

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

Пример объявления:

var MyFlexibleArray: array of Real;

Использование:

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

Начиная с Delphi XE7 стали возможны следующие действия с динамическими массивами:

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])

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

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

type TDynamicCharArray = array of Char;
function Find(A: TDynamicCharArray): Integer;

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

[править | править код]

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

[править | править код]

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

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

[править | править код]

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

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

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

Variant можно смешивать (в выражениях и операторах) с другими вариантами, числовыми, строковыми и булевскими данными. При этом компилятор автоматически выполняет преобразование типа. Варианты, содержащие строки, не могут, однако, индексироваться (V[i] не допустимо).

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;

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

[править | править код]

Стала возможна передача параметров различного типа. В оригинале он назван как «variant open array parameters». Тип данных определяется динамически в процессе выполнения программы. Так же как и в обычном открытом массиве функция High вызывается для определения числа элементов массива. Для объявления используются ключевые слова array of const. Пример:

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]); //передача открытого массива параметров

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

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

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

[править | править код]

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

Введены операторы для проверки и приведения классов is и as динамически в ходе выполнения программы. Появились указатели на методы, для чего введено новое использование ключевого слова object:

type
  TMyMethod = procedure (Sender : Object) of object;

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

[править | править код]

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

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

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

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

Объектная модель в Turbo Pascal:

type
  PMyObject = ^TMyObject;
  TMyObject = object (TObject)
    MyField : PMyType;
    constructor Init;
  end;
//...
var
  MyObject : PMyObject;
begin
  MyObject := New(PMyObject,Init);
  MyObject^.MyField := //...
end;

Новая объектная модель в Object Pascal:

type
  TMyObject = class (TObject)
    MyField : TMyType;
    constructor Create;
  end;
//...
var
  MyObject : TMyObject;
begin
  MyObject := TMyObject.Create;
  MyObject.MyField := //...
end;

Было изменено соглашение об именовании конструкторов и деструкторов. В старой объектной модели вызов New отвечал за распределение памяти, а обращение к конструктору инициализировало выделенную область памяти. В новой модели эти действия выполняет конструктор Create. Начиная с версии Delphi XE появились статические методы класса.[3]

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

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

[править | править код]

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

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;

Общий класс может быть просто специализирован для конкретного типа с использованием ключевого слова specialize:

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

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

Пример:

{объявление}
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;

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

[править | править код]

Начиная с версии среды Delphi 7, фирма Borland стала официально называть язык Object Pascal как Delphi[4].

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

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

[править | править код]

Примечания

[править | править код]
  1. Tesler, Larry (1985). "Object Pascal Report". Structured Language World. 9 (3): 10—7.
  2. Буч Г. Объектно-ориентированное проектирование с примерами применения К.: Диалектика; М.: Конкорд, 1992. — 519 с.
  3. Преимущества перехода на Delphi XE Что нового по сравнению с Delphi 7 Андреано Лануш (Andreano Lanusse) Архивная копия от 15 июня 2016 на Wayback Machine,Ноябрь 2010 г. Embarcadero Technologies Россия, СНГ
  4. Delphi Language Overview (недоступная ссылка)
  5. TopSpeed-компиляторы: не дожили до триумфа Архивировано 11 января 2012 года.
  6. Remobjects Oxygene. Дата обращения: 16 ноября 2015. Архивировано из оригинала 17 ноября 2015 года.
  7. Michaël Van Canneyt. Chapter 6: Classes (англ.). Free Pascal : Reference guide. (декабрь 2011). Дата обращения: 16 января 2012. Архивировано из оригинала 2 февраля 2012 года.