Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi:记录构造函数与工厂函数_Delphi_Constructor_Record - Fatal编程技术网

Delphi:记录构造函数与工厂函数

Delphi:记录构造函数与工厂函数,delphi,constructor,record,Delphi,Constructor,Record,那么,初始化记录的首选方式是什么呢 具有“工厂功能”: TMyRecord = record valueX: integer; valueY: integer; end; function MyRecord(const AValueX, AValueY: integer): TMyRecord; begin result.valueX := AValueX; result.valueY := AValueY; end; var myrec: TMyRecord; begi

那么,初始化记录的首选方式是什么呢

具有“工厂功能”:

TMyRecord = record
  valueX: integer;
  valueY: integer;
end;

function MyRecord(const AValueX, AValueY: integer): TMyRecord;
begin
  result.valueX := AValueX;
  result.valueY := AValueY;
end;

var
  myrec: TMyRecord;
begin
  myrec := MyRecord(1, 2);
end;
或构造器:

TMyRecord = record
  valueX: integer;
  valueY: integer;
  constructor Create(const AValueX, AValueY: integer);
end;

constructor TMyRecord.Create(const AValueX, AValueY: integer);
begin
  self.valueX := AValueX;
  self.valueY := AValueY;
end;

var
  myrec: TMyRecord;
begin
  myrec := TMyRecord.Create(1, 2);
end;
我觉得构造函数更容易封装,但在阅读代码时很容易混淆。它使它看起来像一个缺少免费调用的类。它也更容易打字


为什么您更喜欢其中一个而不是另一个呢?

我更喜欢类,但如果我必须使用记录,我喜欢将它们视为尽可能相似的类。所以我使用记录构造函数

但是在记录和单位上有一个恼人的错误。如果函数返回一条记录(带有方法),则如果要访问这些方法,它将生成一个内部错误。您可以通过将其分配给另一个变量来规避此问题:

type 
  TMyRec = record
    ..
    procedure X;
  end;


function GetRec: TMyRec;



procedure Test;
var
  r1, r2 : TMyRec;
begin
  r1 := GetRec;
  r1.X; // internal error
  r2 := r1;
  r2.X; // No internal error;

我通常不会为记录创建构造函数。它不兼容所有版本(和FPC)。此外,它们通常只在一个地方使用,通常一个fillchar就足够了。

在我创建的一个Delphi项目中,我使用记录而不是类来减少列表上的开销。我在一个动态数组中有几百条记录,所以我创建了两条记录。 第一条记录是关于物品本身的。字段被设置为私有(是的,您可以使用private/protectedwithrecords),并将只读属性添加到public部分。还添加了一个额外的构造函数以正确的方式初始化记录。此设置允许我保护此记录的内容不受其他开发人员的影响。 第二条记录只是前一条记录类型的动态数组的包装器。数组将是私有的,我添加了获取、添加和删除列表中记录的方法。因此,整个列表可以防止其他开发人员误用,并且与常规的TList/TObjectList解决方案相比,开销要小得多

请记住,记录不是类。您不能继承构造函数和其他方法。与WIN32环境中的真正类相比,它们的功能更少。在.NET中,他们又被提升到了班级。 当开发人员可以轻松修改记录中每个字段的内容时,使用add构造函数并不是很有用。您应该使用构造函数来保护这些字段。

我更喜欢像这样的“工厂方法”


封装和记录构造函数中单独的工厂函数泄漏只会混淆IMHO。

我也使用记录构造函数。如果您愿意,可以将其命名为与“Create”不同的名称,这样您就知道它是一条记录。仅供参考,您提到的内部错误问题似乎已在D2010中修复。问题是关于构造函数,而不仅仅是一个方法。若我们对构造函数使用相同的符号,那个么从代码中很难理解它是类的记录还是实例。对于类,它意味着内存泄漏,所以任何看到该代码的人都必须检查它是真正的记录还是类。所以我认为这是一种不好的方法。使用FillChar()初始化带有值的记录有点困难,不是吗?
  function TMyRecord.CreateRec(const AValueX, AValueY: integer): TMyRecord;