使用枚举类型访问动态数组

时间:2016-05-04 15:50:10

标签: arrays delphi enums dynamic-arrays

我处理我们软件的标准数据类。这是当前状态的最小示例:

  TDataOne = (Width, Length, Height);
  TDataTwo = (Diameter, Weight);

  TDatStruct = class;

  TDatSubStructOne = class(TDatStruct)
    public
      myData : array[TDataOne] of double;
      procedure writeToFile(AFileName : string);
  end;
  TDatSubStructTwo = class(TDatStruct)
    public
      myData : array[TDataTwo] of double;
      procedure writeToFile(AFileName : string);
  end;

为了减少代码冗余,我想在TDatStruct中设想一个具有共同写入功能的数据结构。挑战(至少对于业余爱好者来说)是:

  1. mydata的大小可变,具体取决于子结构,并基于不同的枚举类型
  2. 我仍然希望在子结构中使用枚举类型访问mydata
  3. 由于实际代码中不同数组的数量,我不想将子结构数据作为参数传递给公共写入函数
  4. 我唯一的想法(忽略第3点)是将子结构的数组数据作为开放数组参数传递给公共写入过程,如:

    writeToFile(AFileName : string; writeData : array of double);
    

    有没有办法将动态数组与枚举类型或虚拟枚举数组相结合?还是我完全走错了路?

2 个答案:

答案 0 :(得分:4)

  

mydata的大小可变,具体取决于子结构,并基于不同的枚举类型

Delphi具有内在函数LowHigh
您不需要知道数组的大小。

  

我仍然希望在子结构中使用枚举类型访问mydata

使用succpred内在方法遍历枚举。

  

由于实际代码中不同数组的数量,我不想将子结构数据作为参数传递给公共写入函数

你的所有阵列看起来都一样...... 它们只是array of double,虽然元素数量不同。

您可以像这样实施writeToFile

procedure writeArrayToFile(const AFileName : string; const writeData : array of double);
var
  i: integer;
begin
  for i:= low(writeData) to High(writeData) do begin
    WriteADoubleToFile(AFilename, writeData[i]);
  end; {for i}
end;

注意使用const如果你不使用它,数组将被复制到堆栈中,导致大数组的大量延迟。

如果数组是您的类的数据成员,那么您可以简单地编写代码:

procedure TDatStruct.writeToFile(const AFileName : string);
begin
  WriteArrayToFile(FileName, GetMyData^);
end;

请注意,因为父类TDatStruct实际上没有任何数据,所以您需要编写一个可以获取该数据的虚函数。

type 
  TMyArray = array[0..0] of double;
  PMyArray = ^TMyArray; 

.....
 TDatStruct = class
 protected 
   function GetMyData: PMyArray; virtual; abstract;  
 public
   procedure WriteToFile(const Filename: string); //no need for virtual  
 end;

WriteArrayToFile的{​​{3}}会为您解决问题。

请注意writeToFile中的数组参数是“开放数组参数”,这将接受静态和动态数组。

如果你使用不同种类的数组(双/字符串等) 然后使用通用方法。

  

有没有办法将动态数组与枚举类型或虚拟枚举数组相结合?还是我完全走错了路?

动态数组具有可变数量的元素 您无法直接使用枚举对其进行索引 但是,您可以使用open array parameter内在函数将枚举值转换为整数 它也适用于超过256个值的枚举。 文档不正确,会根据需要返回字节,单词或基数。

function FixedArrayToDynamicArray(const input: array of double): TArray<double>;  
begin
  //translate a fixed array to a dynamic array.  
  SetLength(Result, High(input)); 
  Move(input[0], Result[0], SizeOf(Double) * High(input));
end;

代码前的泛型代码:

type 
  TDoubleArray = array of double; 

function FixedArrayToDynamicArray(const input: array of double): TDoubleArray;  
... same from here on. 

答案 1 :(得分:0)

有许多不同的方法,很难说出你的情况最好的方法。

当然,WriteToFile应该在TDatStruct中作为摘要引入:

TDatStruct = class
  public
    procedure WriteToFile(AFileName: string); virtual; abstract;

和后代应该以不同的方式实现它:

TDatStructOne = class (TDatStruct)
  ...
  public
    procedure WriteToFile(AFileName: string); override;

以这种方式,您可以拥有类TDatStruct的对象,它实际上可以是TDatStructOne或TDatStructTwo,但使用它的代码并不需要知道它处理的内容:基本多态性

在这种情况下,您对用于在每个类中存储信息的数据类型有很多自由,实现可能会有所不同。最简单的是:

TDatStructOne = class (TDatStruct)
  public
    Width: Double;
    Length: Double;
    Height: Double;
    procedure WriteToFile(AFileName: string); override;
end;

TDatStructTwo = class (TDatStruct)
  public
    Diameter: Double;
    Weight: Double;
    procedure WriteToFile(AFileName: string); override;
end;

并且在WriteToFile每个后代都有自己的工作。

所以,通过你的挑战:

  1. 您将拥有可变大小的数据,不一定是双打数组,您想要的任何内容(字符串,整数,集等)。
  2. 只要您拥有类TDatStructOne或TDatStructTwo(具体类)的对象,您就可以方便地访问所有这些字段
  3. 没有普通的写程序这样的东西。相反,你有共同的#34;写界面&#34;。您编写obj.SaveToFile(FileName)并将相应保存。