При проектировании библиотек я часто прибегаю к следующему шаблону, который мне не нравится, так как он приводит к большому количеству приведения типов.
Основной шаблон:
Код, использующий библиотеку, передает объект в библиотеку, затем библиотека возвращает объект обратно вызывающему коду. Вызывающий код вынужден приводить объект, поскольку библиотека возвращает общий тип. (Приведенный ниже пример кода)
Библиотека определяет следующие объекты и функции:
TThing = Class
End;
TThingProcessor = Class
Public
Function CreateThing : TThing; Virtual; Abstract;
Procedure ProcessThing (Thing : TThing); Virtual; Abstract;
End;
Procedure DoEverything (Processor : TThingProcessor);
Затем вызывающий код использует библиотеку, переопределяя объекты и вызывая DoEverything следующим образом -
TMyThing = Class(TThing)
Public
X : Integer;
End;
TMyThingProcessor = Class(TThingProcessor)
Public
XSum : Integer;
Function CreateThing : TThing; Override;
Procedure ProcessThing (Thing : TThing); Override;
End;
Function TMyThingProcessor.CreateThing : TThing;
Begin
Result := TMyThing.Create;
End;
Procedure TMyThingProcessor.ProcessThing (Thing : TThing);
Begin
XSum := XSum + (Thing As TMyThing).X;
//Here is the problem, the caller is forced to cast to do anything
End;
Класс процессора также является фабрикой TThing. Библиотека гарантирует, что она будет только передавать TThings соответствующему создателю TThingProcessor, поэтому она работает, но не является типобезопасной. Хотя приведенный выше код немного глуп, поскольку на самом деле он ничего не делает, он показывает, почему ProcessThing нельзя просто перевести на TThing и быть полиморфным - переменную XSum необходимо обновить.
Как я могу реструктурировать код, чтобы приведение не было необходимости? Мне нужно хранить код библиотеки отдельно, но я могу принимать любой тип.
Edit:
Из-за предложения изменено жесткое приведение к приведению, так что оно будет по крайней мере генерировать исключение вместо сбоя в случае несовпадения типов