【问题标题】:Why should we use classes rather than records, or vice versa?为什么我们应该使用类而不是记录,反之亦然?
【发布时间】:2013-10-25 20:00:35
【问题描述】:

我使用 Delphi 已经有一段时间了,但我不是来自 CS 背景,而是“在工作中”学习的 - 主要是从我的老板那里学到的,并通过从网络上收集的点点滴滴来增强,用户指南、示例等。

现在我的老板是老派,开始使用 Pascal 进行编程,并且不一定跟上 Delphi 的最新变化。

就在最近,我一直在想我们的核心技术之一是否“错误”。

我们的大多数应用程序都与 MySQL 交互。一般来说,我们将创建一个record,其结构用于存储从数据库读取的数据,这些记录将存储在TList中。通常,我们将有一个单元来定义我们在应用程序中拥有的各种记录,以及播种和读取记录的函数和过程。我们不使用记录程序,例如概述的here

在查看了一些示例后,我开始想知道我们是否最好使用 classes 而不是记录,但无论哪种方式我都很难找到强有力的指导。

我们正在处理的事情是用户信息:姓名、出生日期、事件、事件类型。或时间表信息:小时、工作等...

【问题讨论】:

    标签: delphi class record


    【解决方案1】:

    最大的区别在于记录是值类型而类是引用类型。简而言之,这意味着:

    1. 对于值类型,当您使用赋值 a := b 时,会创建一个副本。有两个不同的实例,ab
    2. 对于引用类型,当您使用赋值a := b 时,两个变量都引用同一个实例。只有一个实例。

    这样做的主要后果是当你写a.Field := 42 时会发生什么。对于记录,值类型、赋值a.Field 会更改a 中成员的值,但不会更改b 中的成员值。那是因为ab 是不同的实例。但是对于一个类来说,由于ab 都引用同一个实例,那么在执行a.Field := 42 之后你就可以安全地断言b.Field = 42

    没有硬性规定说您应该始终使用值类型或始终使用引用类型。两者都有自己的位置。在某些情况下,最好使用一个,而在其他情况下,最好使用另一个。本质上,决定总是归结为您希望赋值运算符的含义。

    您有一个现有的代码库,并且可能是熟悉它的程序员,并且已经做出了特定的选择。除非您有令人信服的理由转而使用引用类型,否则进行更改几乎肯定会导致缺陷。现有代码(切换到引用类型会改变赋值运算符的含义)和您将来编写的代码中的缺陷(您和您的同事已经对特定上下文中赋值运算符的含义产生了直觉,并且这种直觉会被打破如果你切换)。

    此外,您声明您的类型不使用方法。仅由数据组成且没有与之关联的方法的类型很可能最好由值类型表示。我不能肯定地说,但我的直觉告诉我,最初的开发者做出了正确的选择。

    【讨论】:

    • +1 与我的第一直觉完全相反,但非常务实,所以最后我不得不同意。 OP 应该意识到由于分配可能会影响性能。例如:将记录参数作为const 传递应该是默认值,但话又说回来,这可能会破坏应用程序,我们又回到了务实的尝试
    • @LievenKeersmaekers 是的,我确实考虑过讨论参数传递,但为了简单起见,我选择不这样做。您可以将按值传递的参数视为等效于赋值。参数是局部变量。值传递根据参数的类型复制值或引用。因此,您对赋值的了解同样适用于按值参数传递。
    • 我们通常仅在流式传输结构化数据(例如 TCP、串行或磁盘)时使用记录,在这种情况下,我们使用打包记录来确保大小保持有限。我们将使用类/对象来处理其他所有事情。
    • @DanKelly:recordsclasses 之间的另一个区别是内存管理。当您声明一个记录类型变量时,它的内存由编译器使用堆栈分配。当变量超出范围时,它的内存被自动管理(释放)。当你声明一个类类型变量时,你拥有的是一个引用,你必须调用它的构造函数来分配你将要处理的实例。当您完成使用该对象时,(目前)您有责任通过(直接或不)调用其析构函数来销毁该实例。
    • @Alex 在这种情况下,它们存储在 TList 中,因此它们也是堆分配的。
    猜你喜欢
    • 2010-11-14
    • 2011-12-07
    • 2012-04-11
    • 2010-10-23
    • 1970-01-01
    • 2017-04-09
    • 2017-10-21
    • 2011-10-03
    • 2021-12-10
    相关资源
    最近更新 更多