Вопрос

I created a class called TRecord to store data. I created another class that includes the TRecord class as an objectlist. I add records in an object list using TRecord then when done I set it into the parent class TTableStore.FManyrecords.

I can retrieve the list and the COUNT shows the same number of records but it will not let me retrieve each individual record.

Problem is that I cannot access the record procedures/methods or even define the retrieval of the record. See the last line of pseudo code:

TRecord = class(TObject)
  private
    FDescription : Variant;
    FDirectDeposit : Double;
  public
    function  GetDescription : Variant;
    function  GetDirectDeposit : Double;
    procedure SetDescription(Value: Variant; DoValidation: Boolean = True);
    procedure SetDirect(Value: Double; DoValidation: Boolean = True);
end;

TTableStore = class(TObject)
  private
    FManyRecords : TObjectList ;
    FTitle2 : Variant;
    FNormalEarn : Double;
  public
    function  GetTitle2 : String;
    function  GetNormalEarn : Double;
    function GetManyRecords: TObjectList;
    procedure SetManyRecords(Value: TObjectList; DoValidation: Boolean = True);
    procedure SetTitle2(Value: String; DoValidation: Boolean = True);
    procedure SetNormalEarn(Value: Double; DoValidation: Boolean = True);
end;

private
  FReportObj : TTableStore;
  FRecord: TRecord;
  objectListTemp: TObjectList;

implementation
  objectListTemp := TObjectList.Create(false);
  FRecord := TRecord.create;

  Frecord.SetDescription…
  Frecord.SetDirect…

  objectListTemp.add(FRecord);

//next...
//(get next record… until eof.)

finally
  FReportObj.SetManyRecords(objectListTemp);

//===================== Retreival

  FReportObj : TTableStore;
  fListOfRecords : TObjectList;
  FCurrentRecord : TRecord;

  fListOfRecords := fReportObj.GetManyRecords;
  fListOfRecords.count // (is ok)
  FCurrentRecord := fListOfRecords.Items[1]     // ?????????

The error is TObjList <> TRecord. I am new to Delphi so this might be simple. What am I missing or not understanding? Thanks.

Это было полезно?

Решение

You need to cast the TObject to a TRecord with something like this:

FCurrentRecord := TRecord(FListOfRecords.Items[1]);

It's possible to go the other way around so you can do something like this:

var
  X: TRecord;
  Y: TObject;
begin
  X := TRecord.Create;
  Y := X;
end;

This is because the compiler knows that TRecord descends from TObject but in your code, the compiler has no way of knowing that The TObject in the list is actually a TRecord.

I would suggest using generics instead of a TObjectList. This will create a list of your type of object. You can use this as your TRecordList.

type
  TRecordList = TObjectList<TRecord>;

When you create it you should use:

  FManyRecords := TRecordList.Create;

To do this you will need to include System.Generics.Collections in your uses clause.

Другие советы

Some pepole suggested that you use generics to fix your problem but I think that using generics for this is not necessary as they could hurt your performance a bit not to metnion that they bring lots of their own stuff with it which would increase your EXE size and your application memory usage. Instead you could solve this easily by writing an indexed property to access your internal list items as you would do it othervise if TObjectList wouldn't have been integrated into class. You do this like so:

TRecord = class(TObject)
private
  FDescription : Variant;
  FDirectDeposit : Double;
public
  function  GetDescription : Variant;
  function  GetDirectDeposit : Double;
  procedure SetDescription(Value: Variant; DoValidation: Boolean = True);
  procedure SetDirect(Value: Double; DoValidation: Boolean = True);
end;

TTableStore = class(TObject)
private
  FManyRecords : TObjectList;
protected
  //Used to read record from the internal list which has specific index
  function GetRecord(index: Integer): TRecord;
  //Used to write record on the internal list which has psecific index
  procedure SetRecord(index: Integer; Value: TRecord);
public
  //This property alows you to access any Record from your internal list
  property MyRecord[index: Integer]: TRecord read GetRecord write SetRecord;
  //Used for adding new records to your internal list
  procedure AddRecord(MyRecord: TRecord);
  //Used to remove a record with specific index from your internal list
  procedure RemoveRecord(index: Integer);
end;

implementation

procedure TTableStore.AddRecord(MyRecord: TRecord);
begin
    //We simply call TObjectList.Add method and pass reference to the object
    //we wish to add to the list
    FManyRecords.Add(MyRecord);
end;

function TTableStore.GetRecord(index: Integer): TRecord;
begin
    //We read TObjectList item as we normally would and then we typecast it
    //to TRecord class as this is our expected result.
    result := TRecord(FManyRecords[index]);
end;

procedure TTableStore.RemoveRecord(index: Integer);
begin
    //We simply call TObjectList.delete method passing it a index number of
    //item we wish to remove
    FManyRecords.Delete(index);
end;

procedure TForm4.Button1Click(Sender: TObject);
var MyRecord: TRecord;
    Description: Variant;
begin
    Description := 'Test';
    //We create our record
    MyRecord := TRecord.Create;
    //We set description of our record
    MyRecord.SetDescription(Description);
    //We add our record to the internal table
    MyTableStore.AddRecord(MyRecord);
    //We check to see if record which is stored in out internal table on
    //index 0 to see if its description matches our description variable
    if MyTableStore[0].GetDescription = Description then
    begin
        MessageDlg('It works!',mtInformation,[mbOK],0);
    end;
    //Change description to list record directly
    MyTableStore[0].SetDescription('Test2');
    //Test again to see if description got properly updated
    if MyTableStore[0].GetDescription = 'Test2' then
    begin
        MessageDlg('It works!',mtInformation,[mbOK],0);
    end;
end;

With this you avoid the need to use any generics. Folowing similar approach that I have shown above you can forward any properties or methods from any build in classes (TObjectList is actually built in class in your TTableStore class)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top