zig
zig

Reputation: 4624

How to use property with string index?

I have this code:

type
  TMyClass = class
    private
      procedure SetKeyValue(const Key: WideString; Value: Widestring);
      function GetKeyValue(const Key: WideString): WideString;
    public
      // this works
      property KeyValue[const Index: WideString] : WideString read GetKeyValue write SetKeyValue;

      // this does not compile
      // [Error]: Incompatible types: 'String' and 'Integer'
      property Speed: WideString index 'SPEED' read GetKeyValue write SetKeyValue;
  end;

The Speed property gives me error:

Incompatible types: 'String' and 'Integer'

I need the index to be string. Is it possible to use the index with string value?

Upvotes: 2

Views: 2293

Answers (4)

Whale Sharkslayer
Whale Sharkslayer

Reputation: 9

You can do it this way

    type
  // Class with Indexed properties
  TRectangle = class
  private
    fCoords: array[0..3] of Longint;
    function  GetCoord(Index: string): Longint;
    procedure SetCoord(Index: string; Value: Longint);
  public
    property Left   : Longint Index 0 read GetCoord write SetCoord;
    property Top    : Longint Index 1 read GetCoord write SetCoord;

    property Right  : Longint Index 2 read GetCoord write SetCoord;
    property Bottom : Longint Index 3 read GetCoord write SetCoord;
    property Coords[Index: string] : Longint read GetCoord write SetCoord;
  end;
  
  const
  IndexCoordMap:array [0..3] of TIdentMapEntry
    (
    (Value: 0;   Name: 'Left'),
    (Value: 1;   Name: 'Top'),
    (Value: 2; Name: 'Right'),
    (Value: 3; Name: 'Bottom')
  );
  
  
  
  implementation

{$R *.dfm}

// TRectangle property 'Getter' routine
function TRectangle.GetCoord(Index: string): Longint;
var IntIndex: Integer;
begin
  // Only allow valid index values
  if (IdentToInt(Index, IntIndex, IndexCoordMap))
  then Result := fCoords[IntIndex]
  else raise Exception.Create('Invalid index');
end;

// TRectangle property 'Setter' routine
procedure TRectangle.SetCoord(Index: string; Value: Integer);
var IntIndex: Integer;
begin
  // Only allow valid index values
  if (IdentToInt(Index, IntIndex, IndexCoordMap))
  then fCoords[IntIndex] := Value
    else raise Exception.Create('Invalid index');
end;

Upvotes: 0

user6695319
user6695319

Reputation:

It works very well

property Values[const Name: string]: string read GetValue write SetValue;

{ClassName=class}
private
 fArrayKey: Array of String;{1}
 fArrayValue: Array of String;{2}
 procedure  Add(const Name, Value: string);
 function GetValue(const Name: string): string;
 procedure SetValue(const Name, Value: string);
published
 property Values[const Name: string{1}]: string{2} read GetValue write SetValue;

function   {ClassName.}GetValue(const Name: string): string;
Var I:integer;
Begin
Result := '#empty';
  for I := low(fArrayKey) to high(fArrayKey) do
    if fArrayKey[i]=Name then
       Begin
         Result := fArrayValue[i];
         Break
       End;
If result='#empty' the Raise Exception.CreateFmt('Key %s not found',[name]);
End;
procedure  {ClassName.}SetValue(const Name, Value: string);
var i,j:integer
Begin
j:=-1;
  for I := low(fArrayKey) to high(fArrayKey) do
    if fArrayKey[i]=Name then
       Begin
         j:= i;
         Break
       End;
If j=-1 then Add(name,value) else fArrayValue[i]:= Value;
End;
procedure  {ClassName.}Add(const Name, Value: string);
begin
  SetLength(fArrayKey,Length(fArrayKey)+1);
  SetLength(fArrayValue,Length(fArrayValue)+1);
  fArrayKey  [Length(fArrayKey)  -1] := Name;
  fArrayValue[Length(fArrayValue)-1] := Value;
end;

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Properties_(Delphi)

Upvotes: 0

Remy Lebeau
Remy Lebeau

Reputation: 596397

This is simply not possible with an index specifier, as it only supports integral indexes. You will have to use a separate set of property getter/setter methods:

type
  TMyClass = class
  private
    ...
    procedure SetSpeed(const Value: WideString);
    function GetSpeed: WideString;
  public
    ...
    property Speed: WideString read GetSpeed write SetSpeed;
  end;

procedure TMyClass.SetSpeed(const Value: WideString);
begin
  KeyValue['SPEED'] := Value;
end;

function TMyClass.GetSpeed: WideString;
begin
  Result := KeyValue['SPEED'];
end;

Upvotes: 2

Uwe Raabe
Uwe Raabe

Reputation: 47714

That is not possible. Indexed properties support Integer as index constants only.

See the documentation (own emphasis):

Index specifiers allow several properties to share the same access method while representing different values. An index specifier consists of the directive index followed by an integer constant between -2147483647 and 2147483647. If a property has an index specifier, its read and write specifiers must list methods rather than fields.

Upvotes: 6

Related Questions