Object Pascal: различия между версиями
[непроверенная версия] | [непроверенная версия] |
UniCollab (обсуждение | вклад) Примеры Hello World перенесены в конец статьи |
попытался привести к нормальному виду |
||
Строка 19: | Строка 19: | ||
|license = |
|license = |
||
|website = |
|website = |
||
|extension = .p .pp .pas |
|extension = .p, .pp, .pas |
||
}} |
}} |
||
'''Object Pascal''' |
'''Object Pascal''' ({{lang-en|Объектный Паскаль}}) — [[язык программирования]], разработанный в фирме [[Apple Computer]] в [[1986 год]]у группой [[Ларри Теслер]]а, который консультировался с [[Никлаус Вирт|Никлаусом Виртом]]. Произошёл от более ранней объектно-ориентированной версии [[Паскаль (язык программирования)|Паскаль]]<ref>Буч Г. Объектно-ориентированное проектирование с примерами решения[itbookz.ifolder.ru/7276278]</ref>, называвшейся [[Clascal]], который был доступен на компьютере [[Apple Lisa]]. |
||
== Изменения в Object Pascal от Borland в сравнении с [[Turbo Pascal]] == |
|||
== Изменения в Object Pascal от [[Borland]] в сравнении с [[Turbo Pascal]] == |
|||
Изменения коснулись групп целых, символьных и строковых типов, которые стали разделяться на две категории: |
Изменения коснулись групп целых, символьных и строковых типов, которые стали разделяться на две категории: |
||
* Фундаментальные (fundamental) типы. Их представление в памяти (число битов и наличие знака) строго фиксируется и выдерживается неизменным во всех последующих реализациях Object Pascal для любых операционных систем и компьютерных платформ. |
* '''Фундаментальные (fundamental) типы'''. Их представление в памяти (число битов и наличие знака) строго фиксируется и выдерживается неизменным во всех последующих реализациях Object Pascal для любых операционных систем и компьютерных платформ. |
||
* Родовые (generic) типы. Их представление в памяти не фиксируется и будет реализовано оптимальным способом, в зависимости от реализации для конкретной операционной системы и компьютерной платформы. |
* '''Родовые (generic) типы'''. Их представление в памяти не фиксируется и будет реализовано оптимальным способом, в зависимости от реализации для конкретной операционной системы и компьютерной платформы. |
||
=== Интерфейсы === |
=== Интерфейсы === |
||
Строка 35: | Строка 33: | ||
=== Перегрузка процедур и функций (не ООП) === |
=== Перегрузка процедур и функций (не ООП) === |
||
Введена перегрузка процедур и функций, не являющихся членами объекта или класса. Перегружаются (с помощью ключевого слова '''overload''') отличающиеся типами и числом параметров процедуры и функции : |
Введена перегрузка процедур и функций, не являющихся членами объекта или класса. Перегружаются (с помощью ключевого слова '''overload''') отличающиеся типами и числом параметров процедуры и функции : |
||
<source lang="delphi"> |
|||
procedure Calc(I: Integer); '''overload''';<br /> |
|||
procedure Calc(I: Integer); overload; |
|||
…<br /> |
|||
// ... |
|||
procedure Calc(S: String; J: Integer); '''overload'''; |
|||
procedure Calc(S: String; J: Integer); overload; |
|||
</source> |
|||
=== Динамический массив === |
=== Динамический массив === |
||
Введен для устранения рутинных операций выделения и возвращения памяти в heap-область (кучу), и для того, чтобы избежать случайных ошибок и утечки памяти. Элементы массива должны быть одинаковыми. Нумерация элементов начинается с нуля. |
Введен для устранения рутинных операций выделения и возвращения памяти в heap-область (кучу), и для того, чтобы избежать случайных ошибок и утечки памяти. Элементы массива должны быть одинаковыми. Нумерация элементов начинается с нуля. |
||
Пример объявления: |
Пример объявления: |
||
<source lang="delphi"> |
|||
var MyFlexibleArray: array of Real; |
|||
</source> |
|||
var MyFlexibleArray: '''array of''' Real;<br /> |
|||
Использование: |
Использование: |
||
<source lang="delphi"> |
|||
var |
|||
A, B: |
A, B: array of Integer; |
||
begin |
|||
SetLength(A, 1); //специальная процедура выделения памяти |
|||
A[0] := 1; |
A[0] := 1; |
||
B := A; |
B := A; |
||
B[0] := 2; |
B[0] := 2; |
||
end; |
|||
</source> |
|||
В динамическом массиве тоже возможно задание открытого массива параметров, но тип их должен быть объявлен ранее, например:<br /> |
|||
'''type''' TDynamicCharArray = '''array of''' Char;<br /> |
|||
В динамическом массиве тоже возможно задание открытого массива параметров, но тип их должен быть объявлен ранее, например: |
|||
<source lang="delphi"> |
|||
type TDynamicCharArray = array of Char; |
|||
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). |
||
Строка 74: | Строка 82: | ||
* 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'''; |
|||
D: Double; |
|||
S: String; |
|||
begin |
|||
S: string; |
|||
V1 := 1; //значение типа integer |
|||
begin |
|||
V2 := 359.768; //значение типа real |
|||
V3 := 'Hello world!'; //значение типа string |
|||
end; |
|||
V3 := 'Hello world!'; { значение типа string } |
|||
</source> |
|||
... |
|||
==== Параметры типа вариантного открытого массива ==== |
==== Параметры типа вариантного открытого массива ==== |
||
Стала возможна передача параметров различного типа. |
Стала возможна передача параметров различного типа. |
||
В оригинале он назван как «variant open array parameters». Тип данных определяется динамически в процессе выполнения программы. Так же как и в обычном открытом массиве функция High вызывается для определения числа элементов массива. Для объявления используются ключевые слова ''' |
В оригинале он назван как «variant open array parameters». Тип данных определяется динамически в процессе выполнения программы. Так же как и в обычном открытом массиве функция High вызывается для определения числа элементов массива. Для объявления используются ключевые слова '''array of const'''. Пример: |
||
<source lang="delphi"> |
|||
Пример: |
|||
function Output(const Args: array of const): string; |
|||
var |
|||
I: Integer; |
I: Integer; |
||
begin |
|||
Result := ''; |
Result := ''; |
||
for I := 0 to |
for I := 0 to High(Args) do with Args[I] do |
||
case VType of |
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; |
end; |
||
Result:=Result+ ' '; |
|||
Result := Result + ' '; |
|||
end; |
|||
end; |
|||
... |
|||
//... |
|||
Output(['test', 777, '@', True, 3.14159, TForm]) {передача открытого массива параметров} |
|||
будет возвращена строка: «test 777 @ T 3.14159 TForm». |
|||
Output(['test', 777, '@', True, 3.14159, TForm]); //передача открытого массива параметров |
|||
</source> |
|||
Будет возвращена строка: «test 777 @ T 3.14159 TForm». |
|||
Как видно, имеет свою внутреннюю структуру, обращение к которой дает возможность определить тип данных. В строке вызова функции создается массив, с помощью ''конструктора открытого массива'', который использует квадратные скобки. |
Как видно, имеет свою внутреннюю структуру, обращение к которой дает возможность определить тип данных. В строке вызова функции создается массив, с помощью ''конструктора открытого массива'', который использует квадратные скобки. |
||
Строка 124: | Строка 136: | ||
Введены операторы для проверки и приведения классов '''is''' и '''as''' динамически в ходе выполнения программы. |
Введены операторы для проверки и приведения классов '''is''' и '''as''' динамически в ходе выполнения программы. |
||
Появились указатели на методы, для чего введено новое использование ключевого слова '''object''': |
Появились указатели на методы, для чего введено новое использование ключевого слова '''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''': |
|||
<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 |
MyObject := New(PMyObject,Init); |
||
MyObject^.MyField := //... |
|||
end; |
|||
end; |
|||
</source> |
|||
'''Новая объектная модель в 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> |
|||
type |
|||
TMyObject = '''class''' (TObject) |
|||
MyField : TMyType; |
|||
constructor Create; |
|||
end; |
|||
... |
|||
var |
|||
MyObject : '''TMyObject'''; |
|||
begin |
|||
MyObject:='''TMyObject.Create'''; |
|||
MyObject.MyField:= ... |
|||
end; |
|||
С помощью точки стало возможным обращаться для доступа к методам '''класса'''. Кроме того, было изменено соглашение об именовании конструкторов и деструкторов. В старой объектной модели вызов '''New''' отвечал за распределение памяти, а обращение к конструктору инициализировало выделенную область памяти. В новой модели эти действия выполняет конструктор '''Create'''. |
С помощью точки стало возможным обращаться для доступа к методам '''класса'''. Кроме того, было изменено соглашение об именовании конструкторов и деструкторов. В старой объектной модели вызов '''New''' отвечал за распределение памяти, а обращение к конструктору инициализировало выделенную область памяти. В новой модели эти действия выполняет конструктор '''Create'''. |
||
Строка 171: | Строка 192: | ||
=== [[Обобщенное программирование|Обобщения]] === |
=== [[Обобщенное программирование|Обобщения]] === |
||
<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 |
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 ( |
Разработчики [[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 Implicit(const v: TVector): TPoint; |
|||
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. |
Result.A := Left.A + Right.A; |
||
Result. |
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 |
|||
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; |
|||
</source> |
|||
== Поддержка различными разработчиками == |
== Поддержка различными разработчиками == |
||
Строка 229: | Строка 263: | ||
Язык 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-компиляторы: не дожили до триумфа]</ref>) мультиязыковой среды [[JPI#TopSpeed JPI|TopSpeed]], [[TMT Pascal]], [[Virtual Pascal]], [[PascalABC.NET]], [[Free Pascal]], [[GNU Pascal]]. На Object Pascal основан язык программирования [[Oxygene (язык программирования)|Oxygene]]. |
||
== Примеры Hello |
== Примеры «[[Hello, world!]]» в различных объектных расширениях языка == |
||
= |
{{Начало скрытого блока|Заголовок=Object Pascal от Apple}} |
||
<source lang="pascal"> |
<source lang="pascal"> |
||
program ObjectPascalExample; |
program ObjectPascalExample; |
||
type |
|||
THelloWorld = object |
|||
procedure Put; |
|||
end; |
|||
var |
|||
HelloWorld: THelloWorld; |
|||
procedure THelloWorld.Put; |
|||
begin |
|||
WriteLn('Hello, World!'); |
|||
end; |
|||
begin |
begin |
||
New(HelloWorld); |
|||
HelloWorld.Put; |
|||
Dispose(HelloWorld); |
|||
end. |
end. |
||
</source> |
</source> |
||
{{Конец скрытого блока}} |
|||
{{Начало скрытого блока|Заголовок=Turbo Pascal}} |
|||
=== Turbo Pascal === |
|||
Delphi (для обеспечения обратной совместимости) и [[Free Pascal]] также поддерживают этот вариант синтаксиса. |
|||
<source lang="pascal"> |
<source lang="pascal"> |
||
program ObjectPascalExample; |
program ObjectPascalExample; |
||
type |
|||
PHelloWorld = ^THelloWorld; |
|||
THelloWorld = object |
|||
procedure Put; |
|||
end; |
|||
var |
|||
HelloWorld: PHelloWorld; { это указатель на THelloWorld } |
|||
procedure THelloWorld.Put; |
|||
begin |
|||
WriteLn('Hello, World!'); |
|||
end; |
|||
begin |
begin |
||
Строка 279: | Строка 314: | ||
end. |
end. |
||
</source> |
</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|work=Free Pascal : Reference guide.|lang=en|accessdate=2012-01-16|archiveurl=http://www.webcitation.org/659qF0xXI|archivedate=2012-02-02}}</ref> |
|||
<source lang="delphi"> |
|||
=== Object Pascal в 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|work=Free Pascal : Reference guide.|lang=en|accessdate=2012-01-16|archiveurl=http://www.webcitation.org/659qF0xXI|archivedate=2012-02-02}}</ref> |
|||
<source lang="pascal"> |
|||
program ObjectPascalExample; |
program ObjectPascalExample; |
||
Строка 304: | Строка 340: | ||
end. |
end. |
||
</source> |
</source> |
||
{{Конец скрытого блока}} |
|||
== Примечания == |
== Примечания == |
Версия от 14:45, 30 ноября 2014
Object Pascal | |
---|---|
Семантика | императивная |
Класс языка |
мультипарадигмальный: императивный, структурный, объектно-ориентированный, обобщённый[1], процедурный |
Тип исполнения | компилируемый |
Появился в | 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 |
Медиафайлы на Викискладе |
Object Pascal (англ. Объектный Паскаль) — язык программирования, разработанный в фирме Apple Computer в 1986 году группой Ларри Теслера, который консультировался с Никлаусом Виртом. Произошёл от более ранней объектно-ориентированной версии Паскаль[2], называвшейся Clascal, который был доступен на компьютере Apple Lisa.
Изменения в Object Pascal от Borland в сравнении с Turbo Pascal
Изменения коснулись групп целых, символьных и строковых типов, которые стали разделяться на две категории:
- Фундаментальные (fundamental) типы. Их представление в памяти (число битов и наличие знака) строго фиксируется и выдерживается неизменным во всех последующих реализациях Object Pascal для любых операционных систем и компьютерных платформ.
- Родовые (generic) типы. Их представление в памяти не фиксируется и будет реализовано оптимальным способом, в зависимости от реализации для конкретной операционной системы и компьютерной платформы.
Интерфейсы
Перегрузка процедур и функций (не ООП)
Введена перегрузка процедур и функций, не являющихся членами объекта или класса. Перегружаются (с помощью ключевого слова 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;
В динамическом массиве тоже возможно задание открытого массива параметров, но тип их должен быть объявлен ранее, например:
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».
Как видно, имеет свою внутреннюю структуру, обращение к которой дает возможность определить тип данных. В строке вызова функции создается массив, с помощью конструктора открытого массива, который использует квадратные скобки.
Различия в объектных моделях
Для введения новой объектной модели введено ключевое слово class (в Turbo 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.
Появилась возможность ограничивать видимость членов класса (методы, свойства), которые предназначены для использования только в реализации производных классов. Это дает возможность защищать исходный код от модификации пользователями класса. Такие методы содержатся в секции 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[3].
Язык Object Pascal поддерживается и развивается другими разработчиками. Наиболее серьёзные реализации Object Pascal (помимо Delphi) — это кроссплатформенный TopSpeed Pascal (версия языка Turbo Pascal[4]) мультиязыковой среды TopSpeed, TMT Pascal, Virtual Pascal, PascalABC.NET, Free Pascal, GNU Pascal. На Object Pascal основан язык программирования Oxygene.
Примеры «Hello, world!» в различных объектных расширениях языка
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.
Delphi (для обеспечения обратной совместимости) и Free 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.
В Free Pascal этот вариант синтаксиса доступен в режимах ObjFpc и Delphi.[5]
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.
Примечания
- ↑ Hallvard’s Blog: Highlander2 Beta: Generics in Delphi for .NET
- ↑ Буч Г. Объектно-ориентированное проектирование с примерами решения[itbookz.ifolder.ru/7276278]
- ↑ Delphi Language Overview
- ↑ TopSpeed-компиляторы: не дожили до триумфа
- ↑ Michaël Van Canneyt. Chapter 6: Classes (англ.). Free Pascal : Reference guide. (декабрь 2011). Дата обращения: 16 января 2012. Архивировано 2 февраля 2012 года.
Для улучшения этой статьи желательно:
|