资讯专栏INFORMATION COLUMN

Swift中的值类型和参照类型

jcc / 1887人阅读

摘要:在这篇文章中,我们将深入探讨值类型和参照类型的使用价值,以及如何在某种场景下选择正确的类型。在不存在修改的情况下,值类型和参照类型就没什么区别了。本文首发地址中的值类型和参照类型

在Swift中,类型分为两类:第一种是值类型,该类型的每个实例持有数据的副本,并且该副本对于每个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型。第二种是参照类型,该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),比如类(class)就是参照类型。在这篇文章中,我们将深入探讨值类型和参照类型的使用价值,以及如何在某种场景下选择正确的类型。

它们有什么不同?

值类型最基本的特点就是复制,这影响到它的赋值、初始化、传参等操作。来看看下面的代码示例:

// 值类型示例
struct S { var data: Int = -1 }
var a = S()
var b = a                       // a复制一份,并将副本赋值给了b
a.data = 42                     // a的数据改变了,但是b的并没有改变
println("(a.data), (b.data)") // prints "42, -1"

参照类型的复制行为其实是隐式的创建了一个共享的实例,作为原始类型的参照。下面的例子中,两个变量都会参照唯一的那个共享实例的数据,所当改变这两个变量中任何一个的数据,都会同样作用于原始类型的数据:

// 参照类型示例
class C { var data: Int = -1 }
var x = C()
var y = x       // 将x赋值给y
x.data = 42     // 修改了x的数据,其实是修改了参照数据,那么y的数据也会改变 
println("(x.data), (y.data)") // prints "42, 42"
Mutation在安全性中的角色

选择值类型的一个很重要的原因是可以让你比较容易的理解和掌控你的代码。如果你使用值类型,那么都是唯一的数据值、类型的副本在和你打交道,你对数据的修改只作用于数据所属的类型实例,所以你可以不用担心因为你在某个地方对数据的修改而影响到其他地方的数据。这在多线程环境中非常有用,因为在多线程下,不同的线程有可能会在你不知情的情况下改变数据。发生这种Bug后,调试起来就非常困难。

因为值类型和参照类型的表象区别就在于当你修改类型实例的数据时,它们对原始类型数据的处理方式不同。但是有一种情况,值类型和参照类型的处理方式却又相似,那就是当类型实例的数据为只读的时候。在不存在修改的情况下,值类型和参照类型就没什么区别了。

你可能会觉得这一点很有用,假如说一个class是完全不能被重定义的,那么就比较符合使用Cocoa的NSObject对象的一些习惯,并能很好的保持原本的语义。今天,在Swift你可以通过定义不可改变的存储属性来创建一个不可重定义的类,这样可以避免暴露出的API被修改。事实上,许多普通的Cocoa框架里的类,比如NSURL,都被定义成了不可重定义的类。尽管如此,Swift目前还不提供任何机制像结构体(struct)和枚举(enum)一样去强制使一个class成为不可重定义的类(比如像子类)。

如何选择正确的类型?

如果你想创建一个新类型,那么你应该选择值类型还是参照类型呢?当你使用Cocoa框架时,很多API都是NSObject的子类,那么你就必须要使用参照类型,也就是class。在其他情况下,这里有一些指导建议你可以参考:

使用值类型的情形:

使用==运算符比较实例数据的时候。

你想多带带复制一份实例数据的时候。

当在多线程环境下操作数据的时候。

使用参照类型(比如class)的情形:

当使用===运算符判断两个对象是否引用同一个对象实例的时候。

当上下文需要创建一个共享的、可变的对象时。

在Swift中,ArrayStringDictionary都是值类型。它们的使用方式类似C语言中得int,每一个实例都有一份数据。你不需要进行显示的复制操作去防止数据在你不知情的情况下被修改。更重要的是,你可以跨线程进行传参而不需要考虑同步的问题,因为传递值类型很安全。秉着高安全性的精神,这种类型划分模式能帮助你在Swift中写出更加有可预测性的代码。

本文首发地址:Swift中的值类型和参照类型

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/15717.html

相关文章

  • 【译】Core Graphics, 第二部分:说说 context (上下文)

    摘要:事实上,它在背后维持着一个栈。当你保存了当前的设置,它们被压入一个栈中。将当前的的一份拷贝压入栈中。有栈的概念,这也存在于中。你可以用来将当前的一份拷贝压入栈并且可以通过弹出保存的状态有效地撤销任何对的改变。 原文链接:Core Graphics, Part 2: Contextually Speaking译文原链:【译】Core Graphics, 第二部分:说说 context (...

    Taonce 评论0 收藏0
  • iOS开发④表视图

    摘要:表视图又一下部分组成表头视图表视图最上边的视图表脚视图表视图最下边的视图单元格表视图中每一行的视图节由多个单元格组成,应用于分组列表节头节脚表视图的相关类继承自,且有两个协议和。此外类时单元格类,类时的控制器,用于为节头和节脚提供视图。 概述 表视图组成 表视图是iOS开发中最重要的视图,它以列表的形式展示数据。表视图又一下部分组成: 表头视图:表视图最上边的视图 表脚视图:表视图最...

    bawn 评论0 收藏0
  • 译:Swift ABI (二)

    摘要:为了达成二进制层次上的交互这里应该指的是不同版本编译器生成的结果在二进制上兼容,它们必须共享相同的布局协议。例如,对于一个包含个的传统风格来说,它的值用两个就可以表示了数字,,分别对应三个,它们对应二进制的,和。 泊学翻译自Swift在Github上发布的Swift ABI Manifesto Swift ABI的构成 在实践中,ABI关注的内容是紧密耦合在一起的。但是,作为一个概念模...

    Clect 评论0 收藏0
  • Swift 中的 7 个陷阱以及如何避免

    摘要:原文链接前言伴随着语言的快速发展,我们对于苹果设备编程的认识也发生着变化。这其中的一些陷阱在官方的书里面,但是还有一些书中并没有提及。例如苹果提供了实现的用户体验,系统工具等功能很多框架。 作者: David Ungar,时间:2016/1/27 翻译:BigNerdCoding, 如有错误欢迎指出。原文链接 前言 伴随着Swift语言的快速发展,我们对于苹果设备编程的认识也发生着变...

    sourcenode 评论0 收藏0
  • swift3学习笔记

    摘要:只将需要改变的值声明为变量。使用或者方法来判断一个合是否是另外一个合的子合或者父合并且两个合并不相等。 一直没有时间好好看一下swift,最近复习了一遍语法,这里记录swift学习过程中遇到的一些问题和要点,和Object-C的一些相关特性这里也不做介绍,只记录swift特有的一些特性swift借鉴了很多语言的语法,特别是脚本语言,在swift里,可以看到python语言的一些影子,还...

    txgcwm 评论0 收藏0

发表评论

0条评论

jcc

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<