Sign in Join
Wiki copytemporary

Generics/ru: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Generics/ru

OldNewLine
1+## Вступление
2+
3+[[FPC]] имеет официальную поддержку дженериков(обобщений) в синтаксисе [[Mode ObjFPC|{$mode ObjFPC}]], начиная с версии 2.2, и [[Mode Delphi|{$mode Delphi}]] синтаксис начиная с версии 2.6.0.\
4+Дженерики иногда называют параметризованными типами.\
5+Причина, по которой FPC поддерживает два разных диалекта, Objfpc и Delphi, заключается в том, что у FPC были дженерики до Delphi. Можно использовать модули, написанные в синтаксисе Objfpc, в других модулях, использующих синтаксис Delphi, и наоборот.
6+
7+**Free Generics Library** или **FGL** является нативной реализацией [[Templates|class templates]], написанной в обобщенном синтаксисе Objfpc.\
8+**Rtl-generics package** является реализацией [[Templates|class templates]], написанной в синтаксисе дженериков Delphi, и пытается быть совместимым с библиотекой дженериков Delphi. Этот пакет является стандартным в FPC 3.1.1.+, но есть версия, доступная для FPC 3.0.4.\
9+Обе \[библиотеки\], **FGL** и rtl-generics могут использоваться в обоих режимах.
10+
11+## Модуль fgl
12+
13+Самый простой способ начать работу с дженериками - это использовать [fgl unit](http://freepascal.org/docs-html/current/rtl/fgl/index.html), который является модулем-прототипом для классов дженериков базовой системы. Пока он содержит несколько основных классов:
14+
15+- TFPGList
16+- TFPGObjectList
17+- TFPGInterfacedObjectList
18+- TFPGMap
19+
20+### Как начать
21+
22+В следующем простом примере показано, как хранить несколько экземпляров определенного пользователем класса в списке:
23+
24+``` pascal
25+{$mode objfpc}
26+uses fgl;
27+
28+type
29+ TMyClass = class(TObject)
30+ fld1 : string;
31+ end;
32+
33+ TMyList = specialize TFPGObjectList<TMyClass>;
34+
35+var
36+ list : TMyList;
37+ c : TMyClass;
38+
39+begin
40+ // создаем список и добавляем элемент
41+ list := TMyList.Create;
42+ c := TMyClass.Create;
43+ c.fld1 := 'c1';
44+ list.Add(c);
45+ // получаем элемент из списка
46+ c := list[0];
47+```
48+
49+## Пользовательские классы дженериков
50+
51+Если дженерики, определенные в модуле fgl, не соответствуют вашим потребностям, вам может потребоваться определить свои собственные классы дженериков с нуля, используя базовые языковые примитивы.
52+
53+Класс-дженерик определяется с помощью [[keyword]] (ключевого слова) **generic** перед именем класса и используется в объявлении класса:
54+
55+``` pascal
56+type
57+ generic TList<T> = class
58+ Items: array of T;
59+ procedure Add(Value: T);
60+ end;
61+```
62+
63+Пример реализации класса-дженерика:
64+
65+``` pascal
66+implementation
67+
68+procedure TList.Add(Value: T);
69+begin
70+ SetLength(Items, Length(Items) + 1);
71+ Items[Length(Items) - 1] := Value;
72+end;
73+```
74+
75+Класс-дженерик может быть просто специализирован для определенного типа с помощью ключевого слова **specialize**.
76+
77+``` pascal
78+Type
79+ TIntegerList = specialize TList<Integer>;
80+ TPointerList = specialize TList<Pointer>;
81+ TStringList = specialize TList<string>;
82+```
83+
84+## Другие пункты
85+
86+1. Компилятор анализирует общий тип, но вместо генерации кода он сохраняет все токены в буфере токенов внутри файла PPU.
87+2. Компилятор разбирает специализацию; для этого он загружает буфер токенов из файла PPU и анализирует его снова. Он заменяет общие параметры (в большинстве примеров "T") конкретным заданным типом (например, **LongInt**, **TObject**).
88+
89+Код в основном выглядит так, как будто тот же класс был написан как общий, но с заменой T на данный тип.
90+
91+Поэтому в теории не должно быть различий в скорости между «нормальным» классом и классом-дженериком.
92+
93+## Примеры
94+
95+Пример использования дженериков для написания функции gmax(), которая принимает максимум две еще-не-типизированные переменные. Обратите внимание, что функции имеют пространство имен по имени класса. Недостатком может быть то, что дженерики не могут быть перегружены.
96+
97+``` pascal
98+program UseGenerics;
99+
100+{$mode objfpc}{$H+}
101+
102+type
103+ generic TFakeClass<_GT> = class
104+ class function gmax(a,b: _GT):_GT;
105+ end;
106+
107+ TFakeClassInt = specialize TFakeClass<integer>;
108+ TFakeClassDouble = specialize TFakeClass<double>;
109+
110+ class function TFakeClass.gmax(a,b: _GT):_GT;
111+ begin
112+ if a > b then
113+ result := a
114+ else
115+ result := b;
116+ end;
117+
118+begin
119+ // показать большее из двух целых [чисел]
120+ writeln( 'Integer GMax:', TFakeClassInt.gmax( 23, 56 ) );
121+ // показать большее из двух [чисел] с плавающей точкой
122+ writeln( 'Double GMax:', TFakeClassDouble.gmax( 23.89, 56.5) );
123+ readln();
124+end.
125+```
126+
127+## См. также
128+
129+- [[Templates/ru|Templates]]
130+- [[Generics proposals]]
131+- [[Data Structures, Containers, Collections]]
132+
133+## Внешние ссылки
134+
135+- [Free Pascal: Reference guide - Generics](http://www.freepascal.org/docs-html/ref/refch8.html)
136+- [Используем дженерики в Delphi!](http://keeper89.blogspot.com/2011/07/delphi-1.html)
137+- [Использование стандартных дженериков Delphi для работы с наборами данных](http://proghouse.ru/programming/49-delphi-generics)
138+
139+---
140+*From the Free Pascal wiki, page "Generics/ru", as it stood on 2022-08-06 after a change by Kai Burghardt, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history