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

2023-12-21

拥有 Java 背景,玩过 Swift,为什么要选择 Struct 而不是 Class?看起来它们是同一件事,只是结构提供的功能较少。那为什么选择它呢?


根据非常流行的 WWDC 2015 演讲Swift 中的面向协议编程 (video https://developer.apple.com/videos/wwdc/2015/?id=408, 成绩单 http://asciiwwdc.com/2015/sessions/408?q=protocol),Swift 提供了许多功能,使结构在许多情况下比类更好。

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

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

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

演讲列出了首选课程的这些场景:

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

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

另一方面,Swift 编程语言 https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_108文档有些矛盾:

结构实例总是按值传递,而类 实例始终通过引用传递。这意味着他们是 适合不同类型的任务。当你考虑数据时 项目所需的结构和功能,决定 每个数据结构是否应该被定义为一个类或者一个 结构。

作为一般准则,当一个或多个 以下条件适用:

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

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

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么选择结构而不是类? 的相关文章

随机推荐

  • Laravel Ajax 下拉过滤器

    我正在尝试使用 Ajax 制作一个过滤器 我想在下拉列表中选择的类别发生变化时显示图像 现在 我正在视图中显示所有图像 并且我想要进行 Ajax 调用 返回过滤后的 images 数组以在视图中显示 但我被困住了 我不知道如何从控制器正确返
  • Pandas 交叉表矩阵 dot nansum

    我正在寻求帮助 使用类似 np nansum 的函数从现有数据帧创建子数据帧 我想将此表转换为非空列和的矩阵 dan ste bob t1 na 2 na t2 2 na 1 t3 2 1 na t4 1 na 2 t5 na 1 2 t6
  • 如何查找(并可能删除)个人文件

    Slack API 有一个方法files list 但这似乎只列出在公共频道上共享的文件 而不是在私人对话中共享的文件 作为团队管理员 我想删除旧文件 我不需要查看它们 我可以要求团队成员手动删除它们 但这对他们来说是一个非常缓慢且费力的过
  • 比较修订版本时 SVN 访问被拒绝

    我们正在使用 SVN 存储库 当我们尝试将本地未修改的文件与存储库中文件的最新版本进行比较时 我收到以下错误 换句话说 有人签入了更改 如果我更新 我将得到他们的更改 但首先我想看看他们的更改是什么 不要认为这很重要 但我们正在使用 Xco
  • 在 Windows 中的 django 中设置 cron 作业

    我想设置cronjob in my Django项目 但我正在使用windows 我试过django cron 但它不适用于windows 我该如何使用cronjob在我的项目中安排时间 使用django cron则不然 不能在Window
  • 下拉列表对齐问题(HTML/CSS)

    我以前问过这样的问题 但我使用的代码与上次不同 我正在尝试创建一个下拉菜单 主列表中的某些元素有一个下拉列表 新闻和团队 由于某种原因 它们移到了右侧 我希望下拉列表中的项目与其父项对齐 任何帮助 将不胜感激 Thanks http cod
  • @DataJpaTest 中的存储库初始化为 null

    我正在尝试在 Spring Boot 应用程序中为存储库编写一些测试 但是存储库自动连接为null 测试类的代码如下 package jpa project repo import org junit Assert import org j
  • Ember.ArrayProxy 更改不触发车把 #each 更新

    我怀疑有一种方法可以更新 Ember Array 代理来触发 ember 的通知 但我不知道如何实现 我正在覆盖 内容 属性来更新数组 数组会更新 但视图不会更新 App items Ember ArrayProxy create cont
  • Python:更改 json 解码的列表类型

    在 Python 2 7 中我可以使用object pairs hook在内置 json 模块中更改解码对象的类型 有没有办法对列表做同样的事情 一种选择是遍历作为钩子参数获得的对象 并将它们替换为我自己的列表类型 但是还有其他更聪明的方法
  • 传入通知的增强意图服务警告

    收到通知后 我的日志中出现两个错误 EnhancedIntentService Service took too long to process intent com google android c2dm intent RECEIVE A
  • iOS 15 通讯通知图片未显示

    我一直在尝试将我的 本地和推送 通知更新为通信通知 当用户收到来自其朋友之一的通信事件时 我希望显示的通知包含该朋友的个人资料图片 就像新的 iMessage 应用程序一样 观看专门的 WWDC2021 会议后 我向我的 SwiftUI 应
  • 为什么不调用复制构造函数?

    在此代码中 include
  • 从 C# 调用 powershell cmdlet

    我正在尝试学习如何从 C 调用 PS cmdlet 并且遇到了 PowerShell 类 它对于基本使用来说工作得很好 但现在我想执行这个 PS 命令 Get ChildItem where Length gt 1000000 我尝试通过
  • RequestScoped bean CDI 上的 HttpServletRequest 注入

    我正在寻找一种方法来注入 RequestScoped自定义类到我的 StatelessJAX RS端点 我希望每次应用程序收到请求时 我的自定义类都会注入到我的 JAX RS 端点中 定制类 RequestScoped public cla
  • 使用 Puppeteer 检查元素是否被禁用

    我有一个按钮 其初始状态为disabled
  • Spritekit 和 OpenGL:平滑的烟雾轨迹

    我想在我的 Spritekit 游戏中实现这种效果 其中有一个smooth角色后面的踪迹 See the trail behind the coin in jetpack joyride And this trail behind the
  • 日历预订系统错误

    我有一个 PHP 的 日历预订系统 下面是它的代码片段 我正在运行WampServer2 4
  • 远程:导入错误:没有名为 gitlab 的模块

    我用python写了gitlab hook 并添加到 gitlab 服务器中的 post receive 挂钩 当我从笔记本电脑推送到远程源服务器时 出现以下错误 但当我在 gitlab 服务器中手动运行脚本时它会起作用 我该如何解决问题
  • 无法理解FluentWait中until()方法的实现

    The until 中的方法org openqa selenium support ui FluentWait已超载Predicate
  • 为什么选择结构而不是类?

    拥有 Java 背景 玩过 Swift 为什么要选择 Struct 而不是 Class 看起来它们是同一件事 只是结构提供的功能较少 那为什么选择它呢 根据非常流行的 WWDC 2015 演讲Swift 中的面向协议编程 video htt