小编典典

为什么选择结构而不是类?

all

使用 Swift,来自 Java 背景,为什么要选择 Struct 而不是 Class?似乎它们是相同的东西,结构提供的功能较少。那为什么选择它?


阅读 172

收藏
2022-03-10

共1个答案

小编典典

根据非常流行的 WWDC 2015 演讲 Protocol Oriented Programming in
Swift(视频脚本),Swift
提供了许多特性,使结构在许多情况下优于类。

如果结构相对较小且可复制,则结构更可取,因为复制比使用类对同一实例进行多个引用更安全。当将变量传递给许多类和/或在多线程环境中时,这一点尤其重要。如果您始终可以将变量的副本发送到其他地方,那么您永远不必担心其他地方会更改您下面的变量的值。

使用
Structs,不必担心内存泄漏或多个线程竞相访问/修改变量的单个实例。(对于更有技术头脑的人来说,例外情况是在闭包内捕获结构时,因为它实际上是在捕获对实例的引用,除非您明确将其标记为要复制)。

类也可能变得臃肿,因为一个类只能从一个超类继承。这鼓励我们创建巨大的超类,其中包含许多只是松散相关的不同能力。使用协议,尤其是可以提供协议实现的协议扩展,可以让您消除对实现此类行为的类的需求。

该演讲列出了首选类的这些场景:

  • 复制或比较实例没有意义(例如,Window)
  • 实例生命周期与外部影响相关(例如,TemporaryFile)
  • 实例只是“sinks”——到外部状态的只写管道(egCGContext)

这意味着结构应该是默认的,类应该是后备的。

另一方面,Swift
编程语言
文档有些矛盾:

结构实例总是按值传递,类实例总是按引用传递。这意味着它们适用于不同类型的任务。当您考虑项目所需的数据结构和功能时,请决定是否应将每个数据结构定义为类或结构。

作为一般准则,请考虑在以下一个或多个条件适用时创建结构:

  • 该结构的主要目的是封装一些相对简单的数据值。
  • 当您分配或传递该结构的实例时,期望封装的值将被复制而不是引用是合理的。
  • 结构存储的任何属性本身都是值类型,也应该被复制而不是引用。
  • 该结构不需要从另一个现有类型继承属性或行为。

结构的良好候选示例包括:

  • 几何形状的大小,可能封装了宽度属性和高度属性,都是 Double 类型。
  • 一种引用系列中范围的方法,可能封装了 Int 类型的 start 属性和 length 属性。
  • 3D 坐标系中的一个点,可能封装了 x、y 和 z 属性,每个属性都是 Double 类型。

在所有其他情况下,定义一个类,并创建该类的实例以通过引用进行管理和传递。实际上,这意味着大多数自定义数据结构应该是类,而不是结构。

这里声称我们应该默认使用类并仅在特定情况下使用结构。最终,您需要了解值类型与引用类型在现实世界中的含义,然后您可以就何时使用结构或类做出明智的决定。另外,请记住,这些概念一直在发展,并且
Swift 编程语言文档是在面向协议编程演讲之前编写的。

2022-03-10