类和结构体有相同点,比如属性和方法的定义,下标引用,初始化函数,可扩展,符合规约提供特定功能方法

类比结构体多了如下功能,可继承,可在运行时获得实例类型,可析构以释放内存,可引用计数

结构体实例赋值传递时,内存被另外拷贝一份,所以不会用到引用计数。

我认为上面内容暂不理解没有关系,我也糊涂着呢,毕竟后面有关于初始化,继承,规约,类型解析,引用计数等详细介绍。

定义语法如下:

struct Resolution {
    var width = 0
    var height = 0
}
class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}
//定义实例使用了构造函数,上例两个都是使用了默认的构造函数,都是无参数的
let someResolution = Resolution()
let someVideoMode = VideoMode()

//通过点(.)在引用成员变量
println("The width of someResolution is \(someResolution.width)")
//用法跟C类似,成员的成员
println("The width of someVideoMode is \(someVideoMode.resolution.width)")
//也可以直接对成员的成员赋值,这点跟OC有点区别
someVideoMode.resolution.width = 1280
println("The width of someVideoMode is now \(someVideoMode.resolution.width)")
struct Resolution {
    var width = 0
    var height = 0
}
class VideoMode {
    var resolution = Resolution()
    var interlaced = false
    var frameRate = 0.0
    var name: String?
}
//定义实例使用了构造函数,上例两个都是使用了默认的构造函数,都是无参数的
let someResolution = Resolution()
let someVideoMode = VideoMode()

//通过点(.)在引用成员变量
println("The width of someResolution is \(someResolution.width)")
//用法跟C类似,成员的成员
println("The width of someVideoMode is \(someVideoMode.resolution.width)")
//也可以直接对成员的成员赋值,这点跟OC有点区别
someVideoMode.resolution.width = 1280
println("The width of someVideoMode is now \(someVideoMode.resolution.width)")

请注意命名规则,类和结构体定义时,生成了一种新的swift数据类型,因此,其首字母应该大写,而其成员变量则是首字母小写

结构体实例声明是可以直接根据其成员名形成的构造函数初始化,而类不能使用这种方法

let vga = Resolution(width: 640, height: 480)
let vga = Resolution(width: 640, height: 480)

结构体跟枚举和其他基本类型一样,都属于值类型,即赋值操作是拷贝操作,而不是指针传递。

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd

cinema.width = 2048

println("cinema is now \(cinema.width) pixels wide")
// 打印结果是 "cinema is now 2048 pixels wide"

println("hd is still \(hd.width) pixels wide")
// 打印结果是 "hd is still 1920 pixels wide",由此看见,hd的值没有随cinema变化
let hd = Resolution(width: 1920, height: 1080)
var cinema = hd

cinema.width = 2048

println("cinema is now \(cinema.width) pixels wide")
// 打印结果是 "cinema is now 2048 pixels wide"

println("hd is still \(hd.width) pixels wide")
// 打印结果是 "hd is still 1920 pixels wide",由此看见,hd的值没有随cinema变化

但是类是引用变量(reference type),赋值后,两个类变量将指向同一块地址,类似于C的指针,但是不需要写*。

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

//修改了alsoTenEighty后,原来的tenEighty的值也发生了变化
println("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

//修改了alsoTenEighty后,原来的tenEighty的值也发生了变化
println("The frameRate property of tenEighty is now \(tenEighty.frameRate)")

全等操作符(identity operator)可以比较两个类实例是否是指向同一个地址的,符号是===,不全等操作符是!==

字典(Dictionary)的赋值或参数调用是拷贝操作

数组(Array)的赋值或参数调用在不改变数组大小的情况下是引用操作,如果发生插入元素,删除元素,不同元素个数替换操作时,将发生拷贝操作。

var a = [1, 2, 3]
var b = a
var c = a

println(a[0])
// 1
println(b[0])
// 1
println(c[0])
// 1

a[0] = 42
println(a[0])
// 42
println(b[0])
// 42
println(c[0])
// 42

//执行下面的操作时,a将发生拷贝操作,不再指向原来的地址,也就与b和c没有关系了
a.append(4)
a[0] = 777
println(a[0])
// 777
println(b[0])
// 42
println(c[0])
// 42
var a = [1, 2, 3]
var b = a
var c = a

println(a[0])
// 1
println(b[0])
// 1
println(c[0])
// 1

a[0] = 42
println(a[0])
// 42
println(b[0])
// 42
println(c[0])
// 42

//执行下面的操作时,a将发生拷贝操作,不再指向原来的地址,也就与b和c没有关系了
a.append(4)
a[0] = 777
println(a[0])
// 777
println(b[0])
// 42
println(c[0])
// 42

如果不想改变数组大小的情况下,发生拷贝操作,可以使用unshare方法,比如:

//b执行了unshare后,也有了自己的一份拷贝,不再与c共地址了
b.unshare()
b[0] = -105
println(a[0])
// 777
println(b[0])
// -105
println(c[0])
// 42
//b执行了unshare后,也有了自己的一份拷贝,不再与c共地址了
b.unshare()
b[0] = -105
println(a[0])
// 777
println(b[0])
// -105
println(c[0])
// 42

判断两个数组是否是同一个引用,可以使用(===和!==)操作

if b === c {
    println("b and c still share the same array elements.")
} else {
    println("b and c now refer to two independent sets of array elements.")
}
// 将打印 "b and c now refer to two independent sets of array elements."

//而下面的对比方法可以看到b的子数组是指向同一个引用的
if b[0...1] === b[0...1] {
    println("These two subarrays share the same elements.")
} else {
    println("These two subarrays do not share the same elements.")
}
// prints "These two subarrays share the same elements."
if b === c {
    println("b and c still share the same array elements.")
} else {
    println("b and c now refer to two independent sets of array elements.")
}
// 将打印 "b and c now refer to two independent sets of array elements."

//而下面的对比方法可以看到b的子数组是指向同一个引用的
if b[0...1] === b[0...1] {
    println("These two subarrays share the same elements.")
} else {
    println("These two subarrays do not share the same elements.")
}
// prints "These two subarrays share the same elements."

如果希望赋值时就发生拷贝操作,则使用copy方法(但是unshare方法是被建议使用的)

var names = ["Mohsen", "Hilary", "Justyn", "Amy", "Rich", "Graham", "Vic"]
var copiedNames = names.copy()

copiedNames[0] = "Mo"
println(names[0])
// 打印 "Mohsen"
var names = ["Mohsen", "Hilary", "Justyn", "Amy", "Rich", "Graham", "Vic"]
var copiedNames = names.copy()

copiedNames[0] = "Mo"
println(names[0])
// 打印 "Mohsen"