我知道在Delphi中,当你想允许使用索引运算符[]时,你必须做类似的事情,
property Item[index: integer]: integer read GetData; default;
如何在Delphi中实现多维数组,以便允许使用类似的东西:
matrix := TMatrix<integer>.Create(3,3);
matrix[0][2] := 5;
WriteLn(matrix[0][2]);
答案 0 :(得分:6)
你不能那样使用[][]
。但您可以在单个属性中声明多个索引,例如:
type
TMatrix<T> = class
private
function GetData(index1, index2: Integer): T;
procedure SetData(index1, index2: Integer; value: T);
public
constructor Create(dim1, dim2: Integer);
property Item[index1, index2: Integer]: T read GetData write SetData; default;
end;
然后你可以这样做:
matrix := TMatrix<integer>.Create(3,3);
matrix[0, 2] := 5;
WriteLn(matrix[0, 2]);
答案 1 :(得分:1)
如果您愿意,可以使用[][]
来访问元素。如果您的类型是一个数组(二维或锯齿状动态),那么这种访问元素的方法将被烘焙到该语言中。对于用户定义的类型,您需要实现它。
无法在用户定义类型的单个步骤中实现[][]
。您需要做的是将过程分成两个独立的部分。第一部分是实现[]
以返回矩阵的一行。然后在该行上实现[]
以返回一个元素。这是一个例子:
type
TMatrix<T> = class
public
type
TRow = record
private
FMatrix: TMatrix<T>;
FRowIndex: Integer;
function GetItem(ColIndex: Integer): T; inline;
procedure SetItem(ColIndex: Integer; const Value: T); inline;
public
property Items[ColIndex: Integer]: T read GetItem write SetItem; default;
end;
private
FData: TArray<TArray<T>>;
function GetRow(RowIndex: Integer): TRow; inline;
public
constructor Create(RowCount, ColCount: Integer);
property Rows[RowIndex: Integer]: TRow read GetRow; default;
end;
{ TMatrix<T>.TRow }
function TMatrix<T>.TRow.GetItem(ColIndex: Integer): T;
begin
Result := FMatrix.FData[FRowIndex, ColIndex];
end;
procedure TMatrix<T>.TRow.SetItem(ColIndex: Integer; const Value: T);
begin
FMatrix.FData[FRowIndex, ColIndex] := Value;
end;
{ TMatrix<T> }
constructor TMatrix<T>.Create(RowCount, ColCount: Integer);
begin
inherited Create;
SetLength(FData, RowCount, ColCount);
end;
function TMatrix<T>.GetRow(RowIndex: Integer): TRow;
begin
Result.FMatrix := Self;
Result.FRowIndex := RowIndex;
end;
但是,虽然已经证明这是可能的,但我建议使用带有两个索引的array property更为惯用。这意味着您将使用M[Row,Col]
而非M[Row][Col]
访问矩阵。在所有语言中都找不到这个特定的成语(M[Row,Col]
),因此您可能不熟悉它。支持可能如下所示:
type
TMatrix<T> = class
public
type
TRow = record
private
FMatrix: TMatrix<T>;
FRowIndex: Integer;
function GetItem(ColIndex: Integer): T; inline;
procedure SetItem(ColIndex: Integer; const Value: T); inline;
public
property Items[ColIndex: Integer]: T read GetItem write SetItem; default;
end;
private
FData: TArray<TArray<T>>;
function GetRow(RowIndex: Integer): TRow; inline;
function GetItem(RowIndex, ColIndex: Integer): T; inline;
procedure SetItem(RowIndex, ColIndex: Integer; const Value: T); inline;
public
constructor Create(RowCount, ColCount: Integer);
property Rows[RowIndex: Integer]: TRow read GetRow;
property Items[RowIndex, ColIndex: Integer]: T read GetItem write SetItem; default;
end;
{ TMatrix<T>.TRow }
function TMatrix<T>.TRow.GetItem(ColIndex: Integer): T;
begin
Result := FMatrix.FData[FRowIndex, ColIndex];
end;
procedure TMatrix<T>.TRow.SetItem(ColIndex: Integer; const Value: T);
begin
FMatrix.FData[FRowIndex, ColIndex] := Value;
end;
{ TMatrix<T> }
constructor TMatrix<T>.Create(RowCount, ColCount: Integer);
begin
inherited Create;
SetLength(FData, RowCount, ColCount);
end;
function TMatrix<T>.GetRow(RowIndex: Integer): TRow;
begin
Result.FMatrix := Self;
Result.FRowIndex := RowIndex;
end;
function TMatrix<T>.GetItem(RowIndex, ColIndex: Integer): T;
begin
Result := FData[RowIndex, ColIndex];
end;
procedure TMatrix<T>.SetItem(RowIndex, ColIndex: Integer; const Value: T);
begin
FData[RowIndex, ColIndex] := Value;
end;
请注意,在此版本中,我们选择将Items
作为默认属性。这意味着如果您想要访问一行,则必须明确命名Rows
属性:M.Rows[RowIndex]
。