Строковые коллекции и списки
Когда я переходил с Borland Pascal на Delphi, мне хотелось, чтобы строковые списки (TStringList) были похожи на строковые коллекции (TStringCollection)— ну как можно обойтись без итераторов ForEach?
Но когда я потом попытался перенести приложение Delphi обратно на Turbo Vision, мне сразу захотелось, чтобы строковые коллекции стали похожими на строковые списки.
Добавление и удаление строк в коллекциях по сравнению с удобными операциями списков выглядит как замешивание цемента — в основном из-за простоты и четкости нового синтаксиса Object Pascal.
Сравните код для добавления нового объекта в коллекцию Turbo Vision
AStringColl^.AtInsert(AStringColl^.Count, NewStr(S));
S := PString(AStringColl^.At(Index))^;
с аналогичным кодом для строкового списка Delphi
StringList.Add(S);
S := StringList[Index];
и вы поймете, что я имею в виду. Операции со строковыми коллекциями практически не читаются, а вторая строка приведенного выше фрагмента просто неверна. Если указатель PString равен NIL (то есть в коллекцию добавлена пустая строка), то в строковую переменную S попадет «мусор».
К счастью, на основе TStringCollection можно создать новый объект, облегчающий работу со строковыми коллекциями. Мы добавляем (см. листинг 9.6) безопасный по отношению к указателям метод StrAt и простой метод Add. Теперь можно легко написать код следующего вида:
StrList^.Add(S);
S := StrList^.StrAt(Index);
Знакомый синтаксис облегчает переходы между старым и новым миром — до тех пор, пока с существованием старого мира DOS приходится считаться.
Листинг 9.6. Модуль STRLIST.PAS
{ Создание удобных строковых коллекций в стиле TStringList. } unit StrList; interface uses Objects; type PStrListCollection = ^TStrListCollection; TStrListCollection = object(TStringCollection) function StrAt(Index: Integer): string; procedure Add(const S: string); end; implementation { PtrToStr преобразовывает указатель в строку с отдельной обработкой nil.} function PtrToStr(P: Pointer): string; begin if P = nil then PtrToStr := '' else PtrToStr := PString(P)^; end; { StrAt возвращает строку из строковой коллекции. } function TStrListCollection.StrAt (Index: Integer): string; begin StrAt := PtrToStr(At(Index)); end; { Add добавляет строку в конец строковой коллекции. } procedure TStrListCollection.Add(const S: string); begin AtInsert(Count, NewStr(S)); end; end.