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

发布于 2024-07-27 05:37:44 字数 791 浏览 2 评论 0原文

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

用一个‘工厂函数’:

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;

我觉得构造函数的东西更加封装,但是在阅读代码时很容易感到困惑。 这使得它看起来像是一个没有调用 free 的类。 打字也更多...

为什么你会更喜欢其中一个而不是另一个?

So what will be the preferred way of initializing records?

With a 'factory function':

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;

or a constructor:

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;

I feel that the constructor things more encapsulated, but it makes it easy to get confused when reading code. It makes it look like a class that lack a call to free. It's also more to type...

Why would you prefer one over the other?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

御守 2024-08-03 05:37:44

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

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

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;

I prefer classes, but if I have to use records, I like to treat them as similar as classes as possible. So I use the record constructor.

But there is an annoying bug with records and units. If a function returns a record (with methods), it produces an internal error if you want to access these methods. You can circumvent this by assigning it to another variable:

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;
梦年海沫深 2024-08-03 05:37:44

我更喜欢“工厂方法”,比如

  function TMyRecord.CreateRec(const AValueX, AValueY: integer): TMyRecord;

单独的工厂函数泄漏封装和记录构造函数只会让恕我直言。

I'd prefer "factory method" like

  function TMyRecord.CreateRec(const AValueX, AValueY: integer): TMyRecord;

Separate factory function leaks incapsulation and record constructors just confuse IMHO.

往日 2024-08-03 05:37:44

在我创建的 Delphi 项目中,我使用记录而不是类来减少列表的开销。 我在动态数组中有数百条记录,因此我创建了两条记录。
第一条记录是针对该项目本身的。 这些字段被设为私有(是的,您可以使用私有/受记录保护)并向公共部分添加只读属性。 还添加了一个额外的构造函数以正确的方式初始化记录。 此设置使我能够保护此记录中的内容免受其他开发人员的侵害。
第二条记录只是前一个记录类型的动态数组的包装。 该数组将是私有的,我添加了获取、添加和删除此列表中的记录的方法。 因此,整个列表可以防止其他开发人员误用,并且比常规 TList/TObjectList 解决方案的开销要少得多。

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

In a Delphi project that I created, I used records instead of classes to reduce the amount of overhead on a list. I would have several hundreds of records in a dynamic array so I created two records.
The first record was for the item itself. The fields were made private (yes, you can use private/protected with records) and added read-only properties to the public section. An additional constructor was also added to initialize the record in the correct way. This setup allowed me to protect the contents from this record from other developers.
The second record was just a wrapper around a dynamic array of the previous record type. The array would be private and I added methods to get, add and delete records in this list. As a result, the whole list is protected against mis-use by other developers and also has a lot less overhead than a regular TList/TObjectList solution.

Do keep in mind that records aren't classes. You can't inherit constructors and other methods. They have less functionality than true classes in WIN32 environments. In .NET, they're just promoted to classes again.
And it's not very useful to use add a constructor when developers can easily modify the contents of each and every field in your record. You should use constructors to protect those fields instead.

只为一人 2024-08-03 05:37:44

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

I usually don't create constructors for records. It's not compatible with all versions (and FPC). Moreover typically they are used only in one place and often a fillchar is enough.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文