用Delphi实现记录数据的类化

用Delphi实现记录数据的类化,delphi,ms-access,Delphi,Ms Access,我想我一定是很笨,我是Delphi新手,正在尝试将sql结果读入类中,以便轻松访问它。 我创建了一个虚拟类来进行如下测试: type test_class = class id:integer; job_number:string; cust_name :string ; procedure get_record_data; end; procedure test_class.get_record_data; begin test_class.Create; test_class.

我想我一定是很笨,我是Delphi新手,正在尝试将sql结果读入类中,以便轻松访问它。 我创建了一个虚拟类来进行如下测试:

type
test_class = class
 id:integer;
 job_number:string;
 cust_name :string ;
 procedure get_record_data;
end;
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;
procedure TForm3.Button1Click(Sender: TObject);
begin
 showmessage('Id number is ' + inttostr(test_class.id));
end;
然后我这样调用这个过程:

type
test_class = class
 id:integer;
 job_number:string;
 cust_name :string ;
 procedure get_record_data;
end;
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;
procedure TForm3.Button1Click(Sender: TObject);
begin
 showmessage('Id number is ' + inttostr(test_class.id));
end;
然后我像这样测试我的结果:

type
test_class = class
 id:integer;
 job_number:string;
 cust_name :string ;
 procedure get_record_data;
end;
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;
procedure TForm3.Button1Click(Sender: TObject);
begin
 showmessage('Id number is ' + inttostr(test_class.id));
end;
showmessage行抛出一个编译器错误,该错误表示需要方法标识符

以test\u class.id:=、test\u class.job\u number:=和test\u class.cust\u name:=开头的行 所有这些都为我提供了预期的相同方法标识符以及缺少运算符或分号错误


我做错了什么?有没有更简单的方法?完成此操作后,空值是否会出现问题?

test\u类是一个类型,而不是实例变量。要访问类型为
test\u class
的对象,您需要声明该类型的变量,创建一个实例,然后使用其字段、方法属性。最后,您需要释放该对象的内存

例如(为了不迷惑您,我不会使用
try…finally
):

顺便说一句,按照惯例,Delphi中的用户定义类型以
T
开头,后面是不带下划线的驼峰大小写,如
TTestClass
而不是
test\u class

我猜你不知道类、对象和实例变量的概念。例如,谷歌对于他们的定义有很多信息


在您的
get\u record\u data方法中
如果您想填充它们所属实例的变量,事情将如下所示:

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;

不能将类用作实例。您必须保留对已创建实例的引用,根据您的示例,它可能如下所示

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;
根据@MarjanVenema的建议和评论的要求,最好的版本是:

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;

Test\u类
需要知道它是从什么填充数据的。您试图引用
Form3.ADOQuery1
,但TForm3几乎肯定是类,而不是对象

如果您使用的是Delphi自动生成的代码,那么应该有这样一行代码

var
表格3:TForm3

在你单位的最高层。如果是这种情况,则可以通过在该过程中将所有TForm3替换为Form3来更正代码

更好的解决方案是为
get\u record\u data
过程提供要从中填充的查询:

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;
对于这样一个小对象,最好是直接传入3个变量:


procedure test\u class.set\u object\u data(const-aID:integer;const-aJob\u Number,aCust\u Name:string

我当然不会用它作为答案,因为它是我在学习Delphi时写的,因为这是到另一个网站的链接,但我不久前写了这个:它也不能直接解决你的问题,但这只是我曾经研究过的一个想法。好吗,谢谢。Showmessage可以工作,但是test_class.id:=和其他读取sql的行仍然不能工作。对这些行有什么建议吗?最后添加一个try,你就会得到我的投票。打电话给我很奇怪,但我希望看到良好的实践得到推广。这非常有效,会让我更好地理解。非常感谢。@b嗯,作为一个初级的Delphi程序员,向他展示创建实例而不是使用类函数不是更好吗?@Jandogen我同意,我正在学习他的方法,试图展示如何避免类内的硬引用。既然你提到的方法已经在eKek0答案中显示,那么不必更改我的答案。为什么一个类函数,而不仅仅是一个以ado数据集为参数的构造函数?类函数的名称也不能表示调用者拥有所返回内容的生命周期管理。好的,这很有道理,非常感谢您的帮助。