How to override a property of an inherited class in Delphi?

In one file, I have a base class with an ID property:

type
  TBase = class
  private  
    class function GetID(ACombo: TCombo): Integer; virtual;
    class procedure SetID(ACombo: TCombo; AValue: Integer); virtual;
  public  
    class property ID[ACombo: TCombo]: Integer read GetID write SetID;  
  end;

In the second file, I have another class descending from TBase. By accident, or ignorance, or ever, a new property / field was created with the same name as the existing property / field.

type
  TSubBase = class(TBase)
  private  
    class function GetID(ACombo: TCombo): Integer; override;
    class procedure SetID(ACombo: TCombo; AValue: Integer); override;
  end;

And use these classes as follows:

  TBaseClass = class of TBase;

  function Base(): TBaseClass;

implementation

var
  BaseInstance: TBaseClass;

function Base(): TBaseClass;
begin
  if not Assigned(BaseInstance) then
  begin
     if SOME_PARAM then
      BaseInstance:= TBase
    else
      BaseInstance:= TSubBase;
  end;
  Result := BaseInstance;
end;

if Base.StationCode[cmbStation] = SOME_VALUE then

But when compiling, I got an error:

[DCC Error] uMyFile.pas(69): E2355 Class property accessor must be a class field or class static method


I also tried using static keywords ... and based on the advice from colleagues below, some workaround was found.

type
  TBase = class
  private  
    class function GetIDStatic(ACombo: TCombo): Integer; static;
    class procedure SetIDStatic(ACombo: TCombo; AValue: Integer); static;    
    class function GetID(ACombo: TCombo): Integer; virtual; abstract;
    class procedure SetID(ACombo: TCombo; AValue: Integer); virtual; abstract;
  public  
    class property ID[ACombo: TCombo]: Integer read GetIDStatic write SetIDStatic;  
  end;

  TSubBase = class(TBase)
  private  
    class function GetID(ACombo: TCombo): Integer; override;
    class procedure SetID(ACombo: TCombo; AValue: Integer); override;
  end;

  TBaseClass = class of TBase;

  function Base(): TBaseClass;

implementation

var
  BaseInstance: TBaseClass;

function Base(): TBaseClass;
begin
  if not Assigned(BaseInstance) then
  begin
     if SOME_PARAM then
      BaseInstance:= TBase
    else
      BaseInstance:= TSubBase;
  end;
  Result := BaseInstance;
end;

class function TBase.GetIDStatic(ACombo: TCombo): Integer; static;
begin
  Result := BaseInstance.GetID(ACombo);
  // Or maybe below ?
  // Result := Base().GetID(ACombo); 
end;

class procedure TBase.SetIDStatic(ACombo: TCombo; AValue: Integer); static;
begin
  BaseInstance.SetID(ACombo, AValue);
  // Or maybe below ?
  // Base().SetID(ACombo, AValue); 
end;

But in this last option, the implementation is ugly, and I agree with David to leave the “dreams” of an approach using the properties of the class AND SIMPLE REACTOR, as described below:

  class properties ID[ACombo: TCombo]: Integer ....
  =>> 
  class function GetID(ACombo: TCombo): Integer; virtual;
  class pocedure SetID(ACombo: TCombo; AValue: Integer); virtual; 

Thank you all for digging there!

+4
2

: " ...

, TBase, TSubBase . TBase . - Delphi .

http://docwiki.embarcadero.com/RADStudio/XE5/en/Methods#Class_Methods

Self , ( , .) C, Self C. , Self , (). Self .

, , , cqall. - :

class function GetIDStatic(ACombo: TCombo): Integer; static;
var RealClass: TBaseClass;
begin
  RealClass := Self; /// will not compile !!!
  Result := RealClass.GetID(ACombo);
end;

...

, Self

, , call-. , . - .

, ,

if Base().n.StationCode[cmbStation] = SOME_VALUE then

, .

+3

:

, . , .

:

. class static .

, , , . , .

+2

All Articles