В пособии также рассматриваются анонимные методы и процедурные ссылки.
Словарь терминов
- generics - дженерики, генерики, параметризованные классы, шаблоны, обобщения;
- Типы данных: string – строка, record – запись;
- implicit conversion - неявное приведение (типа);
IV. Создание обобщённой записи
Давайте изучим кое-что ещё и попробуем разработать простенькую, но полезную запись TNullable<T>. Идея состоит в том, чтобы создать запись, которая сможет иметь значения типа T, либо nil. Вы наверное уже задумывались о необходимости такого типа, например для представления значений Null из баз данных.
Эта запись будет содержать два поля: FValue типа T, и булевое поле FIsNil. Для чтения полей, созданы два свойства. Мы будем использовать лишь операторы неявного приведения (типов), чтобы построить значения этого типа.
unit Generics.Nullable; interface type TNullable<T> = record private FValue: T; FIsNil: Boolean; public class operator Implicit(const Value: T): TNullable<T>; class operator Implicit(Value: Pointer): TNullable<T>; class operator Implicit(const Value: TNullable<T>): T; property IsNil: Boolean read FIsNil; property Value: T read FValue; end; |
За дополнительной информацией о перегрузке операторов я советую обратиться к франкоязычной статье La surcharge d'opérateurs sous Delphi 2006 Win32, которую написал Laurent Dardenne (примечание переводчика: я не нашёл аналогичного материала на русском языке). |
Таким образом, это неизменяемый тип (объект, чьё состояние не может быть изменено после создания).
Реализация трех операторов преобразования достаточно проста. Второй (с параметром Pointer) нужен для того, чтобы можно было делать присвоение : = nil.
uses SysUtils; resourcestring sCantConvertNil = 'Cannot convert to nil'; sOnlyValidValueIsNil = 'The only valid value is nil'; class operator TNullable<T>.Implicit(const Value: T): TNullable<T>; begin Result.FValue := Value; Result.FIsNil := False; end; class operator TNullable<T>.Implicit(Value: Pointer): TNullable<T>; begin Assert(Value = nil, sOnlyValidValueIsNil); Result.FIsNil := True; end; class operator TNullable<T>.Implicit(const Value: TNullable<T>): T; begin if Value.IsNil then raise EConvertError.Create(sCantConvertNil); Result := Value.FValue; end; |
Использовать эту запись можно так:
var Value: Integer; NullValue: TNullable<Integer>; begin NullValue := 5; WriteLn(Integer(NullValue)); NullValue := nil; if NullValue.IsNil then WriteLn('nil') else WriteLn(NullValue.Value); NullValue := 10; Value := NullValue; WriteLn(Value); end; |
Результат выполнения будет таким:
5
nil
10
Всё понятно? Это просто чудесно, учитывая, что я не дал ни единого пояснения. Это лишний раз доказывает, что дженерики это также просто как пирог :-). (примечание переводчика: не знаю почему автор считает что пирог – это просто. Я как-то пробовал испечь один, и скажу честно - программирование намного проще) (в оригинале была идиома "as easy as pie", которая переводится как "проще простого")
Полный исходный код Generics.Nullable доступен для скачивания в конце учебника.
- Оригинальный текст: Sébastien Doeraene. Copyright ©2008-2009.
- Перевод: Алексей Тимохин. Copyright ©2009.
- Дата публикации: 13 ноября 2008 года
- Дата перевода: 10 июля 2009 года.
Публикации по теме
- Подробное оглавление
- Примечания к “переводу”
- I. Введение
- II. Повседневное использование на примере TList<T>
- III. Создание обобщённого класса.
- IV. Создание обобщённой записи
- V. Ограничения обобщённых типов
- VI. Использование в качестве параметра более чем одного типа
- VII. Другие типы дженериков
- VIII. Обобщённые методы
- IX. RTTI и дженерики
- Завершающее слово и ссылка на скачивание исходников (не переведено).
easy as pie - идиоматическое выражение, обозначающее "очень простое действие" (этимология - отличие cake от pie, то есть сравнительная простота). Адекватный перевод - "как два пальца ... " (нет, грубо), лучше "как два байта переслать". Но есть много других хороших русских выражений.
ОтветитьУдалитьСпасибо за замечание Alex (особенно за этимологическую справку)!
ОтветитьУдалитьп.с. я всё-таки оставлю свою дословную версию (к ней довольно неплохо приклеилась моя несмешная шутка), да и для использования любой из этиъ фраз придётся заменять простоту дженериков на простоту действий над ними, а это как-то не комильфо.
ОтветитьУдалитьТогда лучше перевести "easy as pie", как "проще пареной репы". Хотя, на вкус...
ОтветитьУдалить