При разработке библиотек я часто прибегаю к следующему шаблону, который мне не нравится, так как это приводит к большому количеству тиков.
Избегайте кастинга при передаче объектов через библиотечный код (в Delphi)
Основная картина:
код с использованием библиотеки руки объект в библиотеке, библиотека затем передает объект обратно в вызывающий код. Вызывающий код вынужден выдать объект, так как библиотека возвращает общий тип. (Урезанный пример кода ниже)
Библиотека определяет следующие объекты и функцию:
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 в соответствующий твингпроцессор, который их создал, поэтому он работает, но не безопасен для типов. Хотя приведенный выше код немного глуп в том, что он на самом деле ничего не делает, он показывает, почему ProcessThing нельзя просто переключить на TThing и быть полиморфным - переменная XSum нуждается в обновлении.
Как я могу реструктурировать код, чтобы сделать бросок ненужным? Мне нужно сохранить код библиотеки отдельно, но иметь возможность принимать любой тип.
Edit: Изменена жесткие преобразованный в литом из-за предложения, так что, по крайней мере, два исключения вместо аварии в случае несогласованных типов
Я думаю, что http://stackoverflow.com/questions/681522/casting-between-parent-and-child-classes-in-delphi "может повлиять на то, что вы пытаетесь сделать – RobS
Спасибо за link, было полезно читать.Я не думаю, что это применимо напрямую, но думать о реструктуризации подобным образом - это бросать идеи для меня, хотя я ничего не смог сфокусировать. – David