首页 > 其他分享 >Swift的值类型和引用类型

Swift的值类型和引用类型

时间:2022-12-08 18:33:35浏览次数:58  
标签:personA name rectangleA length 实例 引用 类型 Swift

在Swift中,类型分为两类:

第一种是值类型,该类型的每个实例持有数据的副本,并且该副本对于每个实例来说是独一无二的一份,比如结构体(struct)、枚举(enum)、元组(tuple)都是值类型。

第二种是引用类型,该类型的实例共享数据唯一的一份副本(在native层面说的话,就是该类型的每个实例都指向内存中的同一个地址),比如类(class)就是引用类型。

在这篇文章中,我们将深入探讨值类型和引用类型的使用价值,以及如何在某种场景下选择正确的类型。

它们有什么不同?

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

struct Rectangle {
    var length = 10
    var width = 0
}
    var rectangleA = Rectangle()
    var rectangleB = rectangleA // rectangleA复制一份赋给rectangleB
    rectangleA.length = 20
    print("rectangleA.length = \(rectangleA.length), rectangleB.length = \(rectangleB.length)")
    // 打印结果:rectangleA.length = 20, rectangleB.length = 10
    // 结论:rectangleA的length值被修改了,rectangleB的length值没有被修改

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

class Person {
    var name: String = "zhangsan"
}
    var personA = Person()
    var personB = personA
    personA.name = "wangwu"
    print("personA.name = \(personA.name), personB.name = \(personB.name)")
    // 打印结果: personA.name = wangwu, personB.name = wangwu
    // 结论:personA的name值被修改了,personA的name值也被修改了

Mutation在安全性中的角色

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

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

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

如何选择正确的类型?

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

使用值类型的情形:

  • 使用==运算符比较实例数据的时候。
  • 你想单独复制一份实例数据的时候。
  • 当在多线程环境下操作数据的时候。

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

  • 当使用===运算符判断两个对象是否引用同一个对象实例的时候。
  • 当上下文需要创建一个共享的、可变的对象时。

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

参考:http://www.devtalking.com/articles/swift-value-and-reference-types/

标签:personA,name,rectangleA,length,实例,引用,类型,Swift
From: https://www.cnblogs.com/songyuliang-geek/p/16966938.html

相关文章

  • Java中String类型判空
    根据之前的学习,我们已经知道在Java中String类型是不可以通过==直接判等的,而应该通过equals()那么在Java中String类型要如何判空呢? 在最开始,我以为判空是这样进行的——......
  • (1)Redis 基本类型
     ​​https://redis.io/​​  ​​http://redisdoc.com/​​ 中文一、库 redis默认16个库,0-15。默认端口号6379使用某个库 select0测试服务器是否连通ping//返......
  • app直播源码,js实现上传图片类型+大小+尺寸验证
    app直播源码,js实现上传图片类型+大小+尺寸验证html代码: <inputtype="file"name="files"id="file"onchange="verificationPicFile(this)">​js代码: //图片类型......
  • redis中如何查看hash类型的key?
    hash类型的key127.0.0.1:34999>typeucf_mlruntime#gIdVerSethash127.0.0.1:34999>  查看key的所有字段和值 hgetall<key>  示例127.0.0.1:3499......
  • redis中,如何查看某个key的类型?
    命令:type<key>  示例:127.0.0.1:34999>typeucf_mlruntime#gIdVerSethash#hash类型127.0.0.1:34999>127.0.0.1:34999>typetestk......
  • [转]MySQL数据类型详解
    原文地址:https://www.cnblogs.com/lteal/archive/2013/03/04/2943061.htmlMySQL数据类型,可以被分为3类:数值类型、日期和时间类型以及字符串(字符)类型 方括号(“[”和......
  • C++学习---cstdio的源码学习分析01-类型定义
    引言cstdio文件是C++对stdio.h头文件的封装,StandardInputandOutputLibrary,定义了一系列标准输入输出函数,包括文件操作(fopen/fclose等),格式化打印(printf/scanf)等。通......
  • 名师课堂|Python基础教程 2 变量与数据类型
    学习目标注释的分类及语法变量的作用定义变量认识数据类型一、注释的分类注释最大的作用,是能够增强程序的可读性在Python中,注释分为两类:单选注释和多行注释1.单行注释只能......
  • Oracle数据库学习笔记四——存储过程的值传递和引用传递
    编程语言中的4种子例程:由两种行为定义,即形式值是否返回以及参数列表是值传递还是引用传递。如果返回输出,子例程就是函数,如果不返回,就是过程。所以4中子例程为:1.值传递函......
  • VBA学习笔记3-数据结构类型SortedList
    https://blog.csdn.net/lyfegf/article/details/103750912?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7ERate-......