深入理解Swift中的变量与常量

前言

最近在学习Swift这门新语言,对于熟练掌握OC编程的iOS开发者来说其实很容易上手,但Swift的确在语法和编程习惯上改变了很多,对于从未了解OC语言而从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中类型推断。就像上面的连续申明变量a、b、c的代码中我们并没有明确指出a、b、c的类型,编译器则是通过你给a、b、c赋的值来推断a、b、c的类型分别为:Int类型、Double类型、String类型。

但是在某些必要时刻我们是需要给申明的变量或常量提供类型标注的,以此来明确他们能够存储的值。添加类型标注的方法是在变量或常量的名字后边加一个冒号,再跟一个空格,最后加上要使用的类型名称(这里和OC中不太一样,需要大家适应一下),如下所示的代码效果其实和上面的是一样的:

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中变量和常量的命名相较于OC中更加灵活多变,但是仍然有上面的规定需要注意,而且他们的命名尽量做到见名知意,以便于开发人员之间的协同合作。这里我给大家列出了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()

第一行代码的意思:首先在内存中的堆区创建一个内存地址为0x7faa31616bb0 的UIView类型的对象,然后在内存中的栈区申明一个名为view0的常量指向该对象,即view0中保存的是0x7faa31616bb0这个地址,而且该常量的值是不可变的(这不废话吗),即view0中保存的内存地址不能变了。

第二行代码的意思: 在堆区又创建一个新的内存地址为0x7f9890c062b0的UIView类型的对象,然后在栈区又申明一个名为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 是常量还是变量并没有关系。

总结

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

变量的值可以修改的本质是其保存的内存地址可以修改。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • 详解Swift编程中的常量和变量

    常量 常量指的是程序无法在其执行期间改变的固定值. 常量可以是任何像整型常量,浮点常量,字符常量或字符串的基本数据类型.也可以是枚举常量. 这些常量和常规变量处理一样,只是它们的值不能在定义后进行修改. 声明常量 使用常量时,则必须使用关键字 let 声明它们如下: 复制代码 代码如下: let constantName = <initial value> 下面是一个简单的例子来说明如何在 Swift 中声明一个常量: 复制代码 代码如下: import Cocoa let constA =

  • Swift 常量与变量实例详解

    1.声明 swift用let对常量的声明,用var对变量进行声明 常量声明之后不可更改,变量声明之后可以对值进行更改 对常量变量的声明代码如下: let maxNum = 1000 var index = 2 注意:常量不能更改 注意:声明的时候关键字与变量名之间要空一个空格 2.连续声明 连续声明每个变量之间用","隔开 var x = 1, y = 2, z = 3 3.变量类型 当变量赋值时,swift自动识别变量类型,种几种机制叫做"type inference&qu

  • Swift中的常量和变量简单概述

    1.在Swift中规定:在定义一个标识符时必须明确说明该标识符是一个常量还是变量 2.使用let来定义常量,定义之后不可以修改 3.使用var来定义变量,定义之后可以修改 4.定义常量和变量 常量:let 标识符的名称 : 类型 = 赋值 变量:var 标识符的名称 : 类型 = 赋值 5.类型的首字母要大写,常量与变量名不能包含数学符号,箭头 6.常量的使用注意 6.1 在开发中,apple建议优先使用常量,只有发现需要修改时再改成变量,因为常量更加安全,不会被任意的修改 6.2 常量的本质.

  • 深入理解Swift中的变量与常量

    前言 最近在学习Swift这门新语言,对于熟练掌握OC编程的iOS开发者来说其实很容易上手,但Swift的确在语法和编程习惯上改变了很多,对于从未了解OC语言而从Swift开始学习iOS开发的新手来说可能上手有一定难度,下面我将这段时间的学习成果结合在网上搜索的知识做一个简单的汇总,希望可以帮助到正在学习Swift的小伙伴们. 变量和常量的定义 Swift开发文档中是这样定义变量和常量的:常量和变量把名字和一个特定类型的值关联起来.常量的值一旦设置好便不能再被更改,然而变量可以在将来被设置为不同

  • Python中的变量与常量

    目录 一.变量.常量的区别 二.变量 1. Python中的变量不需要声明类型 2. 用"="号来给变量赋值 3. 赋值 4. 变量 5. "=" 6. Python允许同时为多个变量赋值 三.常量 四.总结 一.变量.常量的区别 变量:在程序运行过程中,值会发生变化的量. 常量:在程序运行过程中,值不会发生变化的量. 无论是变量还是常量,在创建时都会在内存中开辟一块空间,用于保存它的值. 二.变量 1. Python中的变量不需要声明类型 这是根据Python的动

  • 如何理解Python中的变量

    变量 在Python中,存储一个数据,需要定义一个变量 number1 = 1 #numbe1就是一个变量,用来保存数据:1 number2 = 2 #number2也是一个变量,用来保存数据:2 sum = number1+number2 #sum也是一个变量,用力保存1+2的值 说明: 所谓变量:就是可以改变的量. 程序就是用来处理数据的,而变量就是用来存储数据的 python中的变量不需要指明类型,系统会自动识别 内容扩展: 变量命名 1.下划线或大小写字母开头,后面可跟下划线.大小写字母

  • 初步理解Swift中的泛型

    如果你已经动手写过Swift的程序,相信你已经了解了Swift语言的知识,比如如何写类(class)和结构体(struct).但Swift可没这么简单,呵呵呵.这篇教程主要讲述Swift的一个强力的特性:泛型.这个特性在很多程序设计语言里都非常受欢迎. 对于类型安全(type-safe)语言,一个常见的问题就是如何编写适用于多种类型输入的程序.想象一下,两个整型数相加和两个浮点数相加的程序看起来应该非常类似,甚至一模一样才对.唯一的区别就是变量的类型不同. 在强类型语言中,你需要去定义诸如add

  • 深入理解Swift中的Substring和String

    前言 为文本字符串添加特性或者语法糖在各种编程语言中都很普遍.就拿大家都很熟悉的 C 语言举例,C 字符串本质是一个字符数组(characters array),但是每次输入字符串的时候不用输入 ['h','e','l','l','o'] ,直接打 hello 就可以了,因为这个操作编译器帮你做了. 更高级的语言比如 Swift 处理字符串就不仅仅是当做字符数组了,String 是一个完整的类型,并且有各种特性.我们先来看一下 String 的一个特性:substring. 简单的看一下 Str

  • 深入理解JS中的变量及作用域、undefined与null

    1.Javascript变量作用域 javascript中,变量主要分为局部变量和全局变量两种,对应的作用域也是局部作用域和全局作用域. 1 局部变量和作用域 局部变量一般在函数体内部声明使用: function func(){ var i=12;//局部变量 ...... } 局部变量的作用域在声明这个变量的函数体范围内使用. 局部变量的声明周期从函数被调用执行开始初始化,在函数调用执行完毕之后被销毁. 2.全局变量和作用域 全局变量一般在函数体外面声明: var i=12;//全局变量 fu

  • 深入理解Swift中单例模式的替换及Swift 3.0单例模式的实现

    前言 除了 MVC.MVVM 之外,单例模式可以说是 iOS 开发中另一常见的设计模式.无论是 UIKit 或是一些流行的三方库,我们都能看到单例的身影.而我们开发者本身也会潜意识地将这些类库中的代码当作最佳实践并将其带入日常工作中,哪怕很多人都知道单例存在一些明显的缺陷. 针对单例的缺陷,本文将介绍一些替换或改造单例模式的方法来提升代码质量. 单例的优点 除了上面提到的模仿最佳实践之外,单例的流行肯定也有内在的原因和理由.例如:单例对象保证了只有一个实例的存在,这样有利于我们协调系统整体的行为

  • 深入理解Swift中的访问控制关键字

    前言 在Swift3.0以前有三种访问控制关键字,分别是private.internal和public.而在swift3以后,又在原来的基础上增加了两种访问控制关键字:fileprivate和open.他们可以看作是private和public的进一步细分.下面是各个修饰符的区别以及访问权限排序. 各个修饰符的区别 private swift3.0 private访问级别所修饰的属性或者方法只能在当前类里访问. class A { private func test() { print("thi

  • 深入理解Python中的内置常量

    前言 大家都知道Python内置的常量不多,只有6个,分别是True.False.None.NotImplemented.Ellipsis.__debug__.下面就来看看详细的介绍: 一. True 1. True是bool类型用来表示真值的常量. >>> True True >>> type(True) <class 'bool'> 2. 对常量True进行任何赋值操作都会抛出语法错误. >>> True = 1 SyntaxError

  • Go语言中的变量和常量

    一.变量相关 1.变量声明 C# : int a; Go : var a int; 需要在前面加一个var关键字,后面定义类型 可以使用 var( a int; b string;)减少var 2.变量初始化 var a int = 10 // 正确的使用方式1 var a = 10 // 正确的使用方式2,编译器可以自动推导出v2的类型 a := 10 // 正确的使用方式3,编译器可以自动推导出v3的类型 在:=左侧的变量不应该是已经被声明过的 3.变量赋值 注意:Go语言的新特性 “Sim

随机推荐