Swift正确选择struct和class

概述

struct和class是在应用程序中存储数据和建模行为的不错选择,但它们的相似性可能使您难以选择其中之一。

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

  1. 默认使用struct
  2. 当您需要 Objective-C 互操作性时使用class。
  3. 当您需要控制正在建模的数据的身份时,请使用class。
  4. 使用struct配合protocols来共享行为和实现方法。

默认选择struct

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

使用struct可以更轻松地推理部分代码,而无需考虑应用程序的整个状态。
因为struct是值类型,而类是引用类型,struct的本地更改对应用程序的其余部分不可见,除非您有意将这些更改作为应用程序流程的一部分进行交流。
因此,您可以查看一段代码,并更有信心对该部分中的实例进行显式更改,而不是利用面向切面编程相关的函数调用中进行不可见的更改。

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

如果您使用需要处理数据的 Objective-C API,或者需要将数据模型放入在 Objective-C 框架中定义的现有类层次结构中,则可能需要使用class和类继承来对数据建模。

例如,许多 Objective-C 框架公开了您希望子类化的class。

当需要控制身份时使用class

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

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

重要的提示

谨慎对待身份。
在整个应用程序中普遍共享类实例使逻辑错误的可能性更大。
您可能没有预料到更改大量共享实例的后果,因此正确编写class代码需要做更多的工作。

当不控制身份时使用struct

当创建与身份信息无关的model时,请使用struct。

例如,在查询远程数据库的应用程序中,实例的身份可能完全由外部实体拥有并通过标识符进行通信。
如果应用程序模型的一致性存储在服务器上,可以将记录建模为带有标识符的struct。
在下面的示例中, 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和protocols来建模继承和共享行为

struct和class都支持一种继承形式。
struct和protocols只能采用协议;他们不能从类继承。
但是,您可以使用类继承构建的继承层次结构的种类也可以使用协议继承和结构进行建模。

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

你可能感兴趣的:(Swift正确选择struct和class)