When designing libraries, I often end up resorting to the following pattern, which I don’t like as it results in lots of type-casting.
The basic pattern is:
The code using the library hands an object to the library, the library then hands the object back to the calling code. The calling code is forced to cast the object, as the library hands back a generic type. (Stripped-down code example below)
The library defines the following objects and function:
TThing = Class End; TThingProcessor = Class Public Function CreateThing : TThing; Virtual; Abstract; Procedure ProcessThing (Thing : TThing); Virtual; Abstract; End; Procedure DoEverything (Processor : TThingProcessor);
The calling code then uses the library by overriding the objects and calling DoEverything, as follows –
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;
The processor class is also a TThing factory. The library guarantees that it will only pass TThings to the corresponding TThingProcessor that created them, so it works, but isn’t type-safe. While the code above is a bit stupid in that it doesn’t really do anything, it shows why ProcessThing can’t simply be shifted to TThing and be polymorphic – the XSum variable needs to be updated.
How can I restructure the code so the cast is unnecessary? I need to keep the library code separate but be able to accept any type.
Edit: Changed the hard-cast to an as-cast due to suggestion so it will at least throw exception instead of crash in the case of mismatched types
Are you using Delphi 2009? This is a great use for generics. Change your declarations to:
No more casting.