I work on the standard data class of our software. Here a minimal example of the current state:
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;
In order to reduce code redundancy I would like to conceive a data structure with a common writing function in TDatStruct
. The challenges (at least for me as amateur) are:
mydata
is of variable size depending on the substruct and bases on different enum typesmydata
with an enumerated type in the sub structsThe only idea (neglecting point 3) I have is to pass the array data of the sub structure to the common write procedure as open array parameter like:
writeToFile(AFileName : string; writeData : array of double);
Is there any way to combine a dynamic array with an enumerated type or a virtual enumerated array? Or am I completely on the wrong path?
mydata is of variable size depending on the substruct and bases on different enum types
Delphi has the intrinsic functions Low and High
You don't need to know the size of the array.
I still want to access mydata with an enumerated type in the sub structs
Use the succ
and pred
intrinsic methods to walk through the enumeration.
I do not want to pass the sub structure data as parameter to the common write function because of the number of different arrays in the real code
All of your arrays look the same to me...
They are simply array of double
, albeit with a different number of elements.
You can implement writeToFile
like so:
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;
Note the use of const
if you don't use this the array will be copied to the stack, causing huge delays with big arrays.
If the array is a data member of your class, then you can simply write the code like so:
procedure TDatStruct.writeToFile(const AFileName : string);
begin
WriteArrayToFile(FileName, GetMyData^);
end;
Note that because the parent class TDatStruct
does not actually have any data inside, you'll need to write a virtual function that will get that data.
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;
The open array parameter of the WriteArrayToFile
will fix the issue for you.
Note that the array parameters in writeToFile
is an "open array parameter", this is will accept both static and dynamic arrays.
If you use different kinds of arrays (double/string etc).
Then use a generic method.
Is there any way to combine a dynamic array with an enumerated type or a virtual enumerated array? Or am I completely on the wrong path?
A dynamic array has a variable number of elements.
You cannot index it using a enumeration directly.
However you can translate the enumerated value into an integer using the Ord
intrinsic function.
It also works for enumerations with more than 256 values. The documentation is incorrect, it will return bytes, words or cardinals as needed.
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;
pre-generics the code becomes:
type
TDoubleArray = array of double;
function FixedArrayToDynamicArray(const input: array of double): TDoubleArray;
... same from here on.