在结构和类之间做出选择-swift

687 阅读5分钟

决定如何存储数据和模型行为。

概述

结构和类是将数据存储和建模行为存储在应用程序中的良好选择,但它们的相似性可能会使两者难以选择。

在向应用程序添加新数据类型时,请考虑以下建议,以帮助选择哪个选项有意义。

  • 默认使用结构。
  • 当您需要Objective-C互操作性时,请使用类。
  • 当您需要控制正在建模的数据的身份时,请使用类。
  • 使用结构和协议通过共享实现来采用行为。

默认选择结构

使用结构来表示常见类型的数据。Swift中的结构包含许多仅限于其他语言类的功能:它们可以包括存储属性、计算属性和方法。此外,Swift结构可以通过默认实现采用协议来获取行为。Swift标准库和Foundation为您经常使用的类型使用结构,如数字、字符串、数组和字典。

使用结构可以更轻松地对代码的一部分进行推理,而无需考虑应用程序的整个状态。由于结构是值类型(与类不同)因此,除非您有意将这些更改作为应用程序流程的一部分进行沟通,否则对结构的本地更改不会对应用程序的其余部分可见。因此,您可以查看代码的一部分,并更有信心对该部分中的实例进行显式更改,而不是从切线相关的函数调用中无形地进行更改。

当您需要Objective-C互操作性时使用类

如果您使用需要处理数据的Objective-C API,或者您需要将数据模型安装到Objective-C框架中定义的现有类层次结构中,您可能需要使用类和类继承来建模数据。例如,许多Objective-C框架公开了您应该子类的类。

当您需要控制身份时使用类

Swift中的类具有内置的身份概念,因为它们是引用类型。这意味着,当两个不同的类实例对其每个存储属性具有相同的值时,身份运算符(===)仍然认为它们是不同的。它还意味着,当您跨应用程序共享类实例时,您对该实例所做的更改对代码中包含对该实例引用的每个部分都可见。当您需要实例具有此类身份时,请使用类。常见的用例是文件句柄、网络连接和共享硬件中介,如 CBCentralManager

例如,如果您的类型代表本地数据库连接,则管理对该数据库访问的代码需要完全控制从应用程序查看的数据库状态。在这种情况下,使用类是合适的,但请务必限制应用程序的哪些部分可以访问共享数据库对象。

当您不控制身份时使用结构

当您建模包含具有您无法控制的身份的实体信息的数据时,请使用结构。

例如,在咨询远程数据库的应用程序中,实例的身份可能完全归外部实体所有,并由标识符通信。如果应用程序模型的一致性存储在服务器上,您可以将记录建模为带有标识符的结构。在下面的示例中,“jsonResponse”包含来自服务器的编码“PenPalRecord”实例:

struct PenPalRecord {   
let myID: Int    
var myNickname: String   
var recommendedPenPalID: Int
}
var myRecord = try JSONDecoder().decode(PenPalRecord.self, from: jsonResponse)

对“PenPalRecord”等模型类型的本地更改非常有用。例如,应用程序可能会根据用户反馈推荐多个不同的笔友。由于“PenPalRecord”结构不控制基础数据库记录的身份,因此对本地“PenPalRecord”实例所做的更改不会意外更改数据库中的值。

如果应用程序的另一部分更改了“myNickname”,并将更改请求提交回服务器,则更改不会错误地接收最近被拒绝的笔友推荐。由于“myID”属性被声明为常量,因此它无法在本地更改。因此,对数据库的请求不会意外更改错误的记录。

使用结构和协议来建模继承和共享行为

结构和类都支持一种继承形式。结构和协议只能采用协议;它们不能从类继承。然而,您可以使用类继承构建的继承层次结构类型也可以使用协议继承和结构进行建模。

如果您从头开始构建继承关系,请更喜欢协议继承。协议允许类、结构和枚举参与继承,而类继承仅与其他类兼容。当您选择如何建模数据时,请先尝试使用协议继承构建数据类型的层次结构,然后在结构中采用这些协议。

标准资源库

struct Int (英文)

带有符号的整数值类型。

struct Double (英文)

双精度浮点值类型。

struct String (英文)

属于字符集合的 Unicode 字符串值。

struct Array (英文)

有序的随机存取集合。

struct Dictionary (英文)

元素为键值对的集合。

Swift标准库定义了编写Swift程序的基本功能层,包括: