Value vs. Reference Type

值和引用类型


值语义


var str = "Hello, playground"
var playgroundGreeting = str
playgroundGreeting += "How are you today?"
print(str) # "Hello, playground"

所以 str 的值并没有改变。因为字符串是一个结构体, 而结构体是值类型。那什么是值类型呢? 值类型在赋值给实例或作为参数传递给函数时总是被复制一份。

Swift 的基本类型 - Array, Dictionary, Int, String 等等都是用结构体来实现的, 它们都是值类型。所以在 Swift 中值类型是何等重要。 你应该在模型化你的数据时首先考虑结构体, 然后再考虑类。

引用语义


class GreekGod {
    var name: String
    init(name: String) {
        self.name = name
    }
}

let hecate = GreekGod(name: "Hecate") // 现在有了一个新的名为 "Hecate" 的 GreekGod 实例
let anotherHecate = hecate // 两个常量指向了同一个 GreekGod 类的实例

// 想想在 Perl 语言中的按值传递和按引用传递, 就知道引用能产生副作用
anotherHecate.name = "AnotherHecate"
anotherHecate.name
hecate.name  // AnotherHecate

当你把类的实例赋值给一个常量或变量时, 那个常量或变量就拥有了那个实例的引用, 你也看到了, 引用和复制是不一样的。

img

常量值和引用类型


当值类型和引用类型是常量(使用 let 声明)的时候, 它俩的表现不一样。

// 创建一个名为希腊众神的类
class GreekGod {
    var name: String
    init(name: String) {
        self.name = name
    }
}

let hecate = GreekGod(name: "Hecate") // 现在有了一个新的名为 "Hecate" 的 GreekGod 实例
let anotherHecate = hecate // 两个常量指向了同一个 GreekGod 类的实例

// 想想在 Perl 语言中的按值传递和按引用传递, 就知道引用能产生副作用
anotherHecate.name = "AnotherHecate"
anotherHecate.name
hecate.name  // AnotherHecate

// 创建一个名为希腊神殿的结构体
struct Pantheon {
    var chiefGod: GreekGod // 希腊诸神总是吵架, 所以让这个属性是可变的
}

//  hecate: 赫卡特(司夜和冥界的女神)
let pantheon = Pantheon(chiefGod: hecate)
let zeus = GreekGod(name: "Zeus") // 宙斯
pantheon.chiefGod = zeus // 编译器在这儿会报错

编译器报错: Cannot assign toproperty: 'pantheon' is a 'let' constant。 这个错误告诉你 pantheon 是一个不可变的实例, 这意味着你改变不了它。 声明为常量(let)的值类型修改不了它们的属性, 即使这些属性在类型的实现中是用 var 声明的。 你可以把值类型的实例看作单个完整值的代表, 像一个整数那样。如果你把整数声明为一个常量, 那么之后你就不能修改了。


// 创建一个名为希腊众神的类
class GreekGod {
    var name: String
    init(name: String) {
        self.name = name
    }
}

let hecate = GreekGod(name: "Hecate") 

let zeus = GreekGod(name: "Zeus") // 宙斯

zeus.name = "Zeus Jr"
zeus.name

看到了? 为什么我们不能改变值类型实例常量的属性值(例如 pantheon.chiefGod), 但是我们却能改变引用类型实例常量的属性值?(例如 zeus.name)

因为 zeus 是一个引用类型的实例, zeus 指向 GreekGod 的一个实例, 这个实例通过 GreekGod(name: "Zeus") 生成。当你改变 name 属性存储的值时, 你并没有真正改变 zeus , 它只是 GreekGod 的一个引用。因为你在定义 GreekGod 时让 name 是一个可变存储属性(使用 var), 那你就可以随心所欲修改这个属性的值了。无论你修改了多少次 zeus 的名字, zeus 仍旧指向同一个实例。

同时使用值类型和引用类型


这一章可能会让你疑惑, "我能把值类型放在引用类型里面吗?"; "我能把引用类型放在值类型里面吗?" 答案是可以。后者你可以通过在GreekGod 类中添加一个 Panteon 类型的属性。但是在值类型中使用引用类型你必须非常小心。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容

  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young阅读 3,757评论 1 10
  • 常量与变量使用let来声明常量,使用var来声明变量。声明的同时赋值的话,编译器会自动推断类型。值永远不会被隐式转...
    莫_名阅读 426评论 0 1
  • 基础部分(The Basics) 当推断浮点数的类型时,Swift 总是会选择Double而不是Float。 结合...
    gamper阅读 1,243评论 0 7
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,494评论 18 139
  • 在每个周末的聚会时,好多老乡都会和父亲下上几盘象棋,一群围观者里有我这个好奇的小脑袋。拱卒,架炮,跳马,出车...
    就爱嗑瓜子阅读 692评论 0 3