我们在第四讲时已经介绍过class
和面向对象的相关概念。如果你有其他语言的编程经验,理解面向对象应该不难。今天我们要介绍的struct
也就是结构体
,乍看之下会觉得和Class
很像,但其实它也是一个古老的概念,早在C
语言时代就已存在。不过随着Java
、JavaScript
、Python
等语言逐渐占据C位,结构体的概念已经很少被人提起了。但是近两年,Go
、Rust
的呼声日响,struct
又逐渐回归大众视野,而Swift
因为与C
语言的渊源,自诞生之初就提供了struct
的支持。
今天我们就来看看struct
,相信通过今天对结构体的学习,不仅能帮你更好地掌握Swift
,即使以后遇到其他语言的相关概念,你也可以触类旁通,了然于胸。
先来看一段简单的结构体代码,就用我们在第四讲接触过的案例。
struct Shape {
var numberOfSides = 0
init() {
print("i am here")
}
func simpleDescription() -> String {
return "A shape with \(numberOfSides) sides."
}
}
var shape = Shape()
这段代码几乎与我们之前写的一模一样,唯一的区别,就是把定义类的class
关键字改成了定义结构体的struct
关键字。所以从共性上来说,类
和结构体
是很相似的。它们都可以定义属性和函数。那么struct
到底与class
有什么区别呢?要理解这个问题,我们必须搞懂什么是值传递,什么是引用传递。下面我们来看一些简单的代码:
var a = [1,2,3]
var b = a
第一行定义一个变量a
,并设置其值一系列数字组成的数组,第二行定义了变量
b,并把
a传递给
b`。继续:
a.append(4)
print(a)
print(b)
此时我们把数组a
追加一个数字4
,然后再打印a
、b
两个变量的值,你觉得会是多少呢?动手试一下你就知道:
如图,b
与a
的内容不再相同,也就是说b
的值不受a
变化的影响。像这样,只是在var b = a
的时候,发生了一次a
值到b
值的传递,之后它俩天各一方再无瓜葛,中间的那次=
号赋值就是值传递
。
与值传递
相反的就是引用传递
,这个必须借助class
才能演示,我们来看下面的代码:
class Circle{
var radius:Int
init (_ r:Int){
self.radius = r
}
}
我们定义了一个类,用来描述一个圆形,它有唯一的一个属性radius(半径)
,同时我们可以用构造方法直接提供半径的大小。下面我们定义一个圆形:
var a = Circle(1)
print(a.radius)
显而易见,上面的代码会输出1
。那么我们故技重施,在准备个b
,然后去修改a
的半径,代码如下:
var b = a
a.radius = 2
print(a.radius)
print(b.radius)
大家觉得输出会是什么呢?建议动手实验一下,其实我们得到的输出是:
对,此时a
与b
的半径都是2
了,也就是说,改变a
,也就意味着b
的改变,反过来也是一样的,比如我们继续执行:
b.radius = 3
print(a.radius)
print(b.radius)
这样之后输出也都是3
,其实此时已经不需要再纠结是a
影响了b
还是b
影响了a
,因为**a
就是b
、b
就是a
**,而之所以有这样的结果,就发生在那行var b = a
,关键就在于,这个=
赋值实现的是引用传递
。
简单总结下值传递
和引用传递
的区别,值传递
就是值复制传递
,先复制
一份再传递;引用传递
就是值共享传递
,传递是引用
,而共享的是值
。那么什么是引用
,引用
和值
到底有什么关系呢?
这里给大家举个例子,你想邀请朋友来你家玩,你家
这个物理意义上的一个具体空间就是一个值。而你为了能让朋友找到你家,你抄了好多小纸条,纸条上写清楚了你家的具体地址。这一张张小纸条,就是引用
,把小纸条分给你朋友的过程就是引用传递
。
现在关于=
起到的两种传递效果大家应该很清楚了。那么什么时候发生的是值传递
?什么时候发生的是引用传递
呢?其实非常简单,如果是class
所制造的各种对象
,那么传递就是引用传递
,反之就是值传递
。
除了值传递
和引用传递
的区别,struct
与class
最大的区别就是前者无法享受后者的继承
特性。
理解了这些区别之后,真遇到开发的具体场景,你可能还会有疑惑,针对某一个具体场景,到底该选择struct
还是class
呢?一个简单的技巧告诉大家,就是优先考虑struct
,当struct
无法满足需求的时候,再用class
来替换。因为从struct
改成class
很容易,只要替换一个关键字就行,但是反之往往会遇到困难。当然如果你真这么操作了,也别忘了前文提到的值传递
和引用传递
的区别,相关的代码也应检查一下。
参考资料:
- https://docs.swift.org/swift-book/LanguageGuide/ClassesAndStructures.html
- https://docs.swift.org/swift-book/GuidedTour/GuidedTour.html