Swift中的常量和变量

前言

Swift作为一门新语言,对于熟练掌握Objective-C编程的iOS开发者来说其实很容易上手,但其在语法和编程习惯上改变了很多,对于从未了解Objective-C语言而从Swift开始学习iOS开发的新手来说可能上手有一定难度,下面我将这段时间的学习成果结合官方文档说明做一个简单的汇总,希望可以帮助到正在学习Swift的小伙伴们。
本文主要是介绍Swift中最常用的常量和变量,将从常量和变量的 定义与申明命名规范两者的深入思考 三个方面入手,入门基础篇,重点介绍变量和常量的使用以及区别,希望大家在阅读完本文后都可以熟练使用它们。

常量和变量的定义与申明

常量和变量把名字和一个特定类型的值关联起来。常量的值一旦设置好便不能再被更改,然而变量可以在将来被设置为不同的值。

  • 申明
    常量和变量必须在使用前被声明,使用关键字 let 来声明常量,使用关键字 var 来声明变量。举个简单的例子:
class Person: NSObject {
    let life = 1
    var age = 0
}

这里我们有一个Person类继承NSObject,显然人的生命只有一条应该设置为不可以改变的常量,但是人的年龄是随着时间变化的应该声明为变量,同理,当你在开发过程中有类似需求时应该这样来选择何时使用变量、何时使用常量。
当然我们可以选择一行代码以逗号分隔的形式申明多个简单的变量或常量如下所示:

 var a = 0, b = 1.0, c = "CoderYQ" 
  • Swift中的类型安全和类型推断
    Swift 是一门类型安全的语言,即你必须时刻清楚此时代码需要处理的值的类型,编译器会进行类型检查,任何不匹配的类型都会被标记为错误当然更不能参与运算。当你操作不同类型的值时,类型检查能帮助你避免错误。当然并不是所有的变量和常量都需要明确指出一个确定的类型,如果你没有为申明的变量或常量指定类型,Swift 会使用类型推断的功能推断出合适的类型,通过检查你给变量赋的值,类型推断能够在编译阶段自动的推断出值的类型,这就是Swift中类型推断

    就像上面的连续申明变量abc的代码中我们并没有明确指出三者的类型,编译器则是通过你给三者赋的值来推断三者的类型分别为:Int类型、Double类型、String类型。
    但是在某些必要时刻我们是需要给申明的变量或常量提供类型标注的,以此来明确他们能够存储的值。添加类型标注的方法是在变量或常量的名字后边加一个冒号,再跟一个空格,最后加上要使用的类型名称(这里和Objective-C中不太一样),如下所示的代码效果其实和上面的是一样的:

var a: Int = 0
var b: Double = 1.0
var c: String = "CoderYQ"

如果变量的类型都一样,我们还可以这样申明:

var a, b, c : Double

命名规范

常量和变量的名字几乎可以使用任何字符,甚至包括 Unicode 字符:

let π = 3.14159
let 你好 = "你好世界"
let 🐶🐮 = "dog cow"

官方文档对于命名规范还有这样的要求:

常量和变量的名字不能包含空白字符数学符号箭头保留的(或者无效的)Unicode 码位连线制表符。也不能以数字开头,尽管数字几乎可以使用在名字其他的任何地方。
一旦你声明了一个确定类型的常量或者变量,就不能使用相同的名字再次进行声明,也不能让它改存其他类型的值。常量和变量之间也不能互换,如果你需要使用 Swift 保留的关键字来给常量或变量命名,可以使用反引号( ` )包围它来作为名称。总之,除非别无选择,避免使用关键字作为名字除非你确实别无选择。

总结一句:Swift中变量和常量的命名相较于Objective-C中更加灵活多变,但是仍然有上面的规定需要注意,而且他们的命名尽量做到见名知意,以便于开发人员之间的协同合作。这里我给大家列出了Swift中主要的关键字,希望大家在命名的时候尽量规避他们。

  • 用作声明的关键字:
class、deinit、enum、extension、func、import、init、let、protocol、static、struct、subscript、typealias、var
  • 用作语句的关键字:
break、case、continue、default、do、else、fallthrough、if、in、for、return、switch、where、while
  • 用作表达和类型的关键字:
as、dynamicType、is、new、super、self、Self、Type、__COLUMN__、__FILE__、__FUNCTION__、__LINE__
  • 特定上下文中被保留的关键字:
associativity、didSet、get、infix、inout、left、mutating、none、nonmutating、operator、override、postfix、precedence、prefix、right、set、unowned、unowned(safe)、unowned(unsafe)、weak、willSet

深入思考

经过上面的学习我们已经能够熟练使用常量和变量了,那么两者之间在使用上到底有何区别呢?这里通过例子说明一下:

//通过 UIView() 方法创建一个 UIView 的对象
//(假设系统分配的内存地址为:0x7faa31616bb0)并赋值给申明为 UIView类型 的常量:view0
let view0 : UIView = UIView()

//通过 UIView() 方法创建另外一个 UIView 的对象
//(假设系统分配的内存地址为:0x7f9890c062b0) 并赋值给申明为 UIView类型 的变量:view1
var view1 : UIView = UIView()
  • 第一行代码的意思:首先在内存中的堆区创建一个内存地址为0x7faa31616bb0UIView类型的对象,然后在内存中的栈区申明一个名为view0的常量指向该对象,即view0中保存的是0x7faa31616bb0这个地址,而且该常量的值是不可变的(这不废话吗),即view0中保存的内存地址不能变了。

  • 第二行代码的意思: 在堆区又创建一个新的内存地址为0x7f9890c062b0UIView类型的对象,然后在栈区又申明一个名为view1的变量指向该对象,即view0中保存的是0x7faa31616bb0这个地址,注意此时view1的值是可以改变的,即view1中保存的内存地址是可以变化的。

如果此时执行下面的操作:

//重新创建一个新的 `UIView` 的对象
//(假设系统分配的内存地址为:`0x7f9890c042b0`)并赋值给上面的常量 `view0`
view0 = UIView()

编译器会报这样的错误:

 error: cannot assign to value: 'view0' is a 'let' constant,
change 'let' to 'var' to make it mutable

错误原因:创建一个新的对象有一个新的内存地址,你把新的对象重新赋值给view0,即view0现在指向另一个对象了,相当于将view0中的原来存储的0x7faa31616bb0内存地址修改成了0x7f9890c042b0,但是view0中存储的内存地址一旦赋值了是不能修改的,所以编译器这里就报错了,他建议你将 let 变成 var 来申明 view0

//重新创建一个新的 `UIView` 的对象
//(假设系统分配的内存地址为:`0x7f9890c042b0`)并赋值给上面的变量 `view1`。
view1 = UIView()

这里是不会报错的,因为view1中保存的内存地址是可以修改的。
但是如果我接着执行下面的代码,编译器会不会报错呢?

view0.backgroundColor = UIColor.white
view0.backgroundColor = UIColor.black

代码解释:先将 view0 的背景色设置为白色,然后将view0的背景色修改为黑色(Swift2.0和Swift3.0的修改背景色的方法有所不同,这里使用的是Swift3.0,只是精简了代码,并无本质区别)。
答案是不会的,因为在上面的操作中我并没有修改view0中保存的内存地址,只是通过view0中保存的内存地址拿到view0指向的对象,然后修改对象内部的属性(这里是backgroundColor,还可以是frame等等),和 view0 是常量还是变量并没有关系。

  • 本质区别
    常量的值不可修改的的本质是其保存的内存地址不可修改,但是可以通过该地址拿到地址指向的对象并修改对象的属性。
    变量的值可以修改的本质是其保存的内存地址能够被修改。

看到这里如果你认为关于常量和变量的知识点就这么多,那就大错特错了,Swift引入两者很可能与编程范式有关。具体来说:

  • let和var与函数式编程和命令式编程

letvar 这两个关键字背后蕴藏着两种截然不同的编程范式:函数式编程和命令式编程。Swift对这两者进行了高度融合:它允许你使用引入赋值所带来的简单直观的建模方法。同时也鼓励你使用不变性(常量)缓解各类并发问题。

关于常量和变量与函数式和命令式编程之间更加深入的探讨请参考下面的文章,其缜密的分析、独特的见解以及探索的深度和广度是本文所不能比拟的。
Swift中的 let 和 var
值语义(不是值类型)

最后

如果文中有任何纰漏或错误欢迎在评论区留言指出,本人将在第一时间修改过来;喜欢我的文章,可以关注我以此促进交流学习; 如果觉得此文戳中了你的G点请随手点赞;转载请注明出处,谢谢支持。

下一篇:Swift中闭包的简单使用

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

推荐阅读更多精彩内容