Ik gebruik Delphi XE2. Momenteel heb ik een objectgebaseerd model en elk modelobject kan meerdere validators bevatten. Hier is de vereenvoudigde implementatie van de generieke abstracte klasse validator. De concrete validatieklassen kunnen DoValidate overschrijven en ze hoeven niet het modelobject te casten. De validator wordt gebruikt met behulp van de IValidator-interface.
unit ObjectBasedValidator;
interface
uses
System.SysUtils,
System.Generics.Collections;
type
TModelEntity = class
end;
type
IValidator = interface
procedure Validate(aEntity: TModelEntity; aResult: string);
end;
TValidator = class(TInterfacedObject, IValidator)
private
protected
procedure DoValidate(aEntity: T; aResult: string); virtual; abstract;
public
procedure Validate(aEntity: TModelEntity; aResult: string);
end;
implementation
{ TValidator }
procedure TValidator.Validate(aEntity: TModelEntity; aResult: string);
begin
if not (aEntity is T) then
Exit;
DoValidate(aEntity as T, aResult);
end;
end.
Nu probeer ik het objectmodel te veranderen in interface-gebaseerd. Dus hier is de bijgewerkte validatoreenheid:
unit InterfaceBasedValidator;
interface
type
IModelEntity = interface
end;
type
IValidator = interface
procedure Validate(aEntity: IModelEntity; aResult: string);
end;
TValidator = class(TInterfacedObject, IValidator)
private
protected
procedure DoValidate(aEntity: I; aResult: string); virtual; abstract;
public
procedure Validate(aEntity: IModelEntity; aResult: string);
end;
implementation
{ TValidator }
procedure TValidator.Validate(aEntity: IModelEntity; aResult: string);
begin
//The next line does not compiles
if not (aEntity is I) then
Exit;
DoValidate(aEntity as I, aResult);
end;
end.
Ik zet een commentaar op de regel die niet compileert. Het is duidelijk dat het "I" -generatieve type een GUID moet hebben die hiervoor is gedefinieerd, maar er is geen manier om deze vereiste als een beperking te specificeren.
Een mogelijke oplossing kan zijn om geen generieke abstracte klasse te gebruiken en de interface in de validator te plaatsen, maar ik vraag me af of iemand een idee heeft hoe dit te doen zonder te casten.