如何在Delphi的TMyClass中实现带字符串参数的默认索引属性
实现Delphi类的索引器简化属性访问
原问题背景
现有类定义(修正笔误后):
type TMyItem = class(TObject) private FReference: String; FOtherProperty: TObject; // 修正原代码中属性与字段类型不一致的问题 public property Reference: String read FReference write FReference; // 修正原代码属性声明的语法错误 property OtherProperty: TObject read FOtherProperty write FOtherProperty; end; type TMyListClass = class(TObjectList<TMyItem>) public function IndexOf(const AReference: String): Integer; overload; end; function TMyListClass.IndexOf(const AReference: String): Integer; var I: Integer; begin Result := -1; for I := 0 to Count - 1 do if Items[I].Reference = AReference then begin Result := I; Break; end; end; // 修正原代码FList类型笔误,改为TMyListClass以使用自定义IndexOf方法 type TMyClass = class(TObject) private FList: TMyListClass; public property List: TMyListClass read FList write FList; end;
当前需要通过冗长的代码访问属性:
AMyClass.List.Items[AMyClass.List.IndexOf(ARef)].OtherProperty := AOtherObject;
希望简化为:
AMyClass[ARef].OtherProperty := AOtherObject;
解决方案:给TMyClass添加带参数的默认属性
通过给TMyClass定义带字符串参数的默认属性,内部封装索引查找逻辑,即可实现目标简化写法。
1. 修改TMyClass的定义
添加默认属性Items,并声明对应的读写方法:
type TMyClass = class(TObject) private FList: TMyListClass; function GetItem(const AReference: String): TMyItem; procedure SetItem(const AReference: String; Value: TMyItem); public constructor Create; virtual; destructor Destroy; override; property List: TMyListClass read FList write FList; // 标记为默认属性,接受字符串类型的Reference参数 property Items[const AReference: String]: TMyItem read GetItem write SetItem; default; end;
2. 实现读写方法与构造/析构函数
constructor TMyClass.Create; begin inherited; // 传入True表示自动释放列表内的TMyItem对象,可按需调整 FList := TMyListClass.Create(True); end; destructor TMyClass.Destroy; begin FList.Free; inherited; end; function TMyClass.GetItem(const AReference: String): TMyItem; var Index: Integer; begin Index := FList.IndexOf(AReference); if Index <> -1 then Result := FList.Items[Index] else Result := nil; // 可根据需求改为抛出异常,如:raise Exception.Create('Item not found'); end; procedure TMyClass.SetItem(const AReference: String; Value: TMyItem); var Index: Integer; begin Index := FList.IndexOf(AReference); if Index <> -1 then FList.Items[Index] := Value else FList.Add(Value); // 按需改为抛出异常或其他逻辑 end;
使用效果
现在可以直接通过索引器语法访问目标对象:
// 读取属性 var Obj: TObject; Obj := AMyClass[ARef].OtherProperty; // 设置属性 AMyClass[ARef].OtherProperty := AOtherObject;
关键说明
- 默认属性通过
default关键字标记,Delphi允许类定义一个默认属性,使用时可省略属性名,直接用类实例[参数]的形式访问。 - 读写方法内部复用了
TMyListClass的IndexOf方法,无需重复编写查找逻辑。 - 找不到对应
Reference的Item时,可根据业务需求选择返回nil、抛出异常或自动添加新Item,示例中采用返回nil和自动添加的逻辑,可自行调整。
内容的提问来源于stack exchange,提问作者SiBrit
相关产品推荐
相关产品推荐

