Delphi:记录构造函数与工厂函数
那么初始化记录的首选方式是什么?
用一个‘工厂函数’:
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我更喜欢类,但如果我必须使用记录,我喜欢将它们尽可能地视为类。 所以我使用记录构造函数。
但记录和单位有一个恼人的错误。 如果函数返回一条记录(带有方法),并且您想访问这些方法,则会产生内部错误。 您可以通过将其分配给另一个变量来规避此问题:
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:
我更喜欢“工厂方法”,比如
单独的工厂函数泄漏封装和记录构造函数只会让恕我直言。
I'd prefer "factory method" like
Separate factory function leaks incapsulation and record constructors just confuse IMHO.
在我创建的 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.
我通常不会为记录创建构造函数。 它不兼容所有版本(和 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.