2
votes

I guess I must be dense, I'm new to Delphi and am trying to read a sql result into a class to access it easily. I have created a dummy class to test like this:

type
test_class = class
 id:integer;
 job_number:string;
 cust_name :string ;
 procedure get_record_data;
end;

Then I call the procedure like this:

procedure test_class.get_record_data;
begin
 test_class.Create;
 test_class.id := tform3.adoQuery1.FieldByName('id').AsInteger;
 test_class.job_number := tform3.adoQuery1.FieldByName('job number').AsString;
 test_class.cust_name := tform3.adoQuery1.FieldByName('customer name').AsString;
end;

Then I test my result like this:

procedure TForm3.Button1Click(Sender: TObject);
begin
 showmessage('Id number is ' + inttostr(test_class.id));
end;

The showmessage line throws a compiler error that says Method Identifier Expected.

The lines that start with test_class.id:=, test_class.job_number:= and test_class.cust_name:= all give me the same Method Identifier Expected as well as a Missing Operator or semicolon error.

What am I doing wrong? Is there an easier way to go about this? Once I get this done, will null values present an issue?

3
I certainly won't use this as an answer, because it was written by me while I was still learning Delphi, and because this is a link to another website, but I wrote this a while back: tek-tips.com/faqs.cfm?fid=7420 - Jerry Dodge
Also it doesn't directly solve your issue, but it's just an idea I was researching at one time. - Jerry Dodge

3 Answers

8
votes

You can not use a class as an instance. You will have to keep a reference to the created instance, according your example it could look like this ...

type
Ttest_class=class
 id:integer;
 job_number:string;
 cust_name :string ;
 Class Function get_record_data(ADS:TCustomAdodataset):Ttest_class;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
  TC:Ttest_class;
begin
   TC := Ttest_class.get_record_data(AdoQuery1);
   try
   showmessage('Id number is ' + inttostr(TC.id));
   finally
     TC.Free
   end;
end;


class function Ttest_class.get_record_data(ADS: TCustomAdodataset): Ttest_class;
begin
 Result := Ttest_class.Create;
 Result.id:=ADS.FieldByName('id').AsInteger;
 Result.job_number:= ADS.FieldByName('job number').AsString;
 Result.cust_name:= ADS.FieldByName('customer name').AsString;
end;

As suggested by @MarjanVenema and requested by comment a preferable version:

type
  Ttest_class = class
    id: integer;
    job_number: string;
    cust_name: string;
    Constructor Create(ADS: TCustomAdodataset);
  end;

Constructor Ttest_class.Create(ADS: TCustomAdodataset);
begin
  id := ADS.FieldByName('id').AsInteger;
  job_number := ADS.FieldByName('job number').AsString;
  cust_name := ADS.FieldByName('customer name').AsString;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  TC: Ttest_class;
begin
  TC := Ttest_class.Create(ADOQuery1);
  try
    showmessage('Id number is ' + inttostr(TC.id));
  finally
    TC.Free
  end;
end;
6
votes

test_class is a type and not an instance variable. To access an object of type test_class you need to declare a variable of that type, create an instance and, just then, use its fields, properties of methods. Finally, you need to free the memory of that object.

For example (to not confuse you I won't use a try...finally):

procedure TForm3.Button1Click(Sender: TObject);
var tc: test_class;  //instance variable declaration
begin
  tc := test.class.Create; //creation of the object
  tc.get_record_data; //call a method to fill the class fields
  ShowMessage('Id number is ' + inttostr(tc.id)); //use of the object
  tc.Free; //freeing the memory object
end;

By the way, by convention the user defined types in Delphi begins with T and follows with camel case without underscores, as in TTestClass instead of test_class.

I guess that you don't know the concepts of classes, objects and instance variables. Google for their definitions, there is a lot of information about that, for example this tutorial.


In your get_record_data method if you want to fill the variables of the instance that they belongs, the thing will go like:

procedure test_class.get_record_data ;
begin
  id         := tform3.adoQuery1.FieldByName('id').AsInteger;
  job_number := tform3.adoQuery1.FieldByName('job number').AsString;
  cust_name  := tform3.adoQuery1.FieldByName('customer name').AsString;
end;
1
votes

Test_Class needs to know what it is populating it's data from. You are trying to refer to Form3.ADOQuery1, but TForm3 will almost definitely be the Class, not an object.

If you're using Delphi auto-generated code then there should be a line saying something like

var Form3: TForm3

at the top of your unit. If this is the case then you can correct your code by replacing all TForm3 with Form3 in that procedure.

A better solution is to give your get_record_data procedure the query it is to fill from:

procedure test_class.get_record_data (const aQuery: TADOQuery);
begin
  id         := aQuery.FieldByName('id').AsInteger;
  job_number := aQuery.FieldByName('job number').AsString;
  cust_name  := aQuery.FieldByName('customer name').AsString;
end;

Even better for such a small object is to pass in the 3 variables directly:

procedure test_class.set_object_data(const aID: integer; const aJob_Number, aCust_Name: string