Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refer to a class from within a constant array of record?

I have a class, TiffData that contains abstract methods to load and display data, and a number of ancestor classes like TTiffByte, TTiffAscii, TTiffShort that define those methods.

I also have a constant array or records that lets me look up information about types based on the data type recorded in the IFD.

What I can't figure out, how to store the associated class for each array element.

type
    TtiffType = record
      name  : string;
      bytes : word;
      data  : class;   {  ?  }
      desc  : string;
    end;

const
TiffTypes : array[ 1 .. 18 ] of TTiffType =  (

{01} ( name: 'byte';  bytes : 1; data: TTiffByte;     { ? }
       desc: '8-bit unsigned number.'   ),
{02} ( name: 'ascii';  bytes : 1; data: TTiffAscii;   { ? }
       desc: '8 bit byte that contains a 7 bit ASCII code; the last byte must be NULL (binary zero)'   ),
{03} ( name: 'short';  bytes : 2; data: TTiffShort;   { ? }
       desc: '16-bit (2-byte) unsigned integer.'   ),
...

What I would like to do is hold a reference to the class in the array:

value := TiffTypes[ fldType ].Data.Create;

value.loadFromOffset( offset );
Edit1.Text := value.getShortString;

or hold a constructor in the array:

value := TiffTypes[ fldType ].data;

value.loadFromFile( f, offset, count );
InternalRepresentation := TTiffAscii( value.storage );
like image 560
Rick Avatar asked May 04 '14 23:05

Rick


2 Answers

Since your classes have a common base class, TiffData, you can use class of TiffData in your record, eg:

type
  TtiffType = record
    name  : string;
    bytes : word;
    data  : class of TiffData; // <-- here
    desc  : string;
  end;

Using Data.Create will then work as expected, as long as the constructor for TiffData is declared as virtual and each derived class overrides it.

like image 172
Remy Lebeau Avatar answered Nov 15 '22 05:11

Remy Lebeau


What you need is a meta class.

type
  TTiffDataClass = class of TiffData;

You can then use it like this:

TTiffType = record
  name  : string;
  bytes : word;
  data  : TTiffDataClass;
  desc  : string;
end;

If you have a descendent of the TiffData then you can use that. For example:

TTiffByte= class(TiffData)
end;

This should work:

{01} ( name: 'byte';  bytes : 1; data: TTiffByte;     { ? }
       desc: '8-bit unsigned number.'   ),

As Remi said in his answer, be careful of the constructors.

like image 25
Graymatter Avatar answered Nov 15 '22 07:11

Graymatter