{$mode objfpc} unit uolist; interface type // ------------- Классы узлов списка ------------- // абстрактный класс узла списка TBaseListNode=class private prev, next:TBaseListNode; ... public constructor Create; procedure Show;virtual; abstract; // вывод содержимого узла destructor Destroy; override; ... end; // класс целочисленного узла списка TIntListNode=class(TBaseListNode) private ... public constructor Create(Value:int64); procedure Show;override; ... end; // класс строкового узла списка TStringListNode=class(TBaseListNode) private ... public constructor Create(Value:string); procedure Show;override; ... end; // -------------- различные виды списков -------------- // типы функций обработки элементов списка (глобальная и метод класса) // функция возвращает узел, которым должен быть заменен текущий type TListAction=function(p:TBaseListNode):TBaseListNode; TListActionObj=function(p:TBaseListNode):TBaseListNode; of object; // -------------- Абстрактный класс списка -------------- TBaseList=class private ... public // набор методов для перемещения по списку. function First:TBaseListNode; virtual; abstract; // возвращает первый элемент списка function Next:TBaseListNode; virtual; abstract; // возвращает последующий элемент списка function Last:TBaseListNode; virtual; abstract; // возвращает последний элемент списка function Prev:TBaseListNode; virtual; abstract; // возвращает предыдущий элемент списка // если p=nil, генерируется ИСС EListEmptyBaseNode procedure AddFirst(p:TBaseListNode); virtual; abstract; // если p=nil, генерируется ИСС EListEmptyBaseNode procedure AddLast(p:TBaseListNode); virtual; abstract; // если p=nil и el=nil, генерируется ИСС EListEmpty // если только p=nil, генерируется ИСС EListEmptyBaseNode // если только El=nil, генерируется ИСС EListEmptyAuxNode procedure InsertBefore(var El:TBaseListNode; p:TBaseListNode); virtual; abstract; procedure InsertAfter(var El:TBaseListNode; p:TBaseListNode); virtual; abstract; // если p=nil и prevNode=nil, генерируется ИСС EListEmpty // Если prevNode<>nil, то p игнорируется, удаление производится на базе предыдущего элемента prevNode // Если p<>nil и prevNode=nil, то производится удаление элемента p function Delete(var p:TBaseListNode; predNode:TBaseListNode=nil):TBaseListNode; virtual; abstract; procedure ListAction(proc:TListAction; backward:boolean=false); virtual; abstract; procedure ListAction(proc:TListActionObj; backward:boolean=false); virtual; abstract; overload; function Count:integer; procedure Show; ... end; // Конкретизация классов списка. // Если какой-либо метод (комбинация параметров метода) неприменим из-за ограничений типа списка, // то попытка его вызова должны генерировать специфичную исключительную ситуацию // -------------- Класс односвязного списка -------------- T1List=class(TBaseList) ... end; // -------------- Класс односвязного кольцевого списка -------------- T1CList=class(T1List) ... end; // -------------- Класс двусвязного списка -------------- T2List=class(TBaseList) ... end; // -------------- Класс двусвязного кольцевого списка -------------- T2CList=class(T2List) ... end; implementation end.