1. 类与结构体的比较

属性特征 结构体
定义属性用于存储值
定义方法用于提供功能
定义下标脚本用于允许使用下标语法访问值
定义初始化器用于初始化状态
可以被扩展来实现默认所没有的功能
遵循协议来针对特定类型提供标准功能
继承允许一个类继承另外一个类的特征
类型转换允许你在运行时检查和解释一个类实例的类型
反初始化器允许一个类实例释放任何被其分配的资源
引用计数允许不止一个对类实例的引用

2. 类的定义

class 类名 {

    属性列表

        statement

        ......

    方法列表

        statement

        ......

}

3. 类的 init 初始化方法 (类的构造函数)

class cCar {

    var brand : String

    var speed : Int

    init() {

        self.brand = ""

        self.speed = 0

        print("调用了没有参数的 init 方法")

    }

    init(brand : String, speed : Int) {

        self.brand = brand

        self.speed = speed

        print("调用了含有 brand 和 speed 参数的 init 方法")

    }

    func drive() {

        print("你正在驾驶 \(brand), 时速为 \(speed)公里/小时\n")

    }

}

let car = cCar(brand : "Auti", speed : 80)

car.drive()

let newCar = cCar()

newCar.drive()

    /*

        结果 :

            调用了含有 brand 和 speed 参数的 init 方法

            你正在驾驶 Auti, 时速为 80 公里/小时

            调用了没有参数的 init 方法

            你正在驾驶, 时速为 0 公里/小时

    */

4. 类属性的 setget 方法

Swift 的类中若要用到 setget 方法, 使用 get 方法可以不用带 set 方法, 但是使用 set 方法必须要带 get 方法

class cHero {

    var damage : Int = 10

    var level : Int{

        get{

            return self.damage / 10

        }

        set(update) {

        self.damage += update * 10

        }

    }

}

let hero = cHero()

print(hero.level)

print(hero.damage)

hero.level = 10

print(hero.level)

print(hero.damage)

    /*

        结果 :

            1

            10

            11

            110

    */

5. 类属性的 willSetdidSet 方法

通过给属性添加 willSetdidSet 方法, 可以给类添加属性观察者

属性观察者可以观察属性值的改变, 并且对此作出相应的反应

class cHero {

    var damage : Int = 10

    var level : Int = 3 {

        willSet {

            print("欢迎进入挑战系统, 在这里您可以通过打怪升级")

        }

        didSet {

            if level > oldValue {

                print("挑战成功, 您的英雄升级了!")

            }

            else{

                print("挑战失败!")

            }

        }

    }

}

var 打怪 = 1

for index in 1...10 {

    let hero = cHero()

    hero.level = 打怪

    打怪 += 1

}

    /*

        结果 :

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战失败!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战失败!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战失败!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战成功, 您的英雄升级了!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战成功, 您的英雄升级了!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战成功, 您的英雄升级了!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战成功, 您的英雄升级了!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战成功, 您的英雄升级了!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战成功, 您的英雄升级了!

            欢迎进入挑战系统, 在这里您可以通过打怪升级

            挑战成功,您的英雄升级了!

    */

        //从第四次循环开始, newValue 的值开始比 oldValue 大, 所以使得 hero.level 的值得到了更新,于是输出了挑战成功

6. 类的静态方法

在 Swift 环境中, 可以为类, 结构体和枚举等类型定义静态方法, 也称为类型方法

在对结构体和枚举定义静态方法的时候, 可以使用 static 关键字

如果一个方法不依赖具体实例, 建议将它定义为静态方法

class cMathTool {

    class func sum(number1 : Int, number2 : Int) -> Int {

        return number1 + number2

    }

    class func multiply(number1 : Int, number2 : Int) -> Int {

        return number1 * number2

    }

}

print(cMathTool.sum(number1 : 10, number2 : 20))    //结果 : 30

print(cMathTool.multiply(number1 : 10, number2 : 20))    //结果 : 200

7. 类的 deinit 方法 (类的析构函数)

deinit 函数无法手动调用, 在实例引用计数为 0 的时候, 系统会自动调用

class cFileManager {

    init() {

        print("Loading...")

        print("Writing...")

    }

    deinit {

        print("Deleting...")

    }

}

var fileManager : cFileManager? = cFileManager()

fileManager = nil

    /*

        结果 :

            Loading...

            Writing...

            Deleting...

    */

比较代码 :

class cFileManager {

    init() {

        print("Loading...")

        print("Writing...")

    }

    deinit {

        print("Deleting...")

    }

}

var fileManager : cFileManager? = cFileManager()

//fileManager = nil

    /*

        结果 :

            Loading...

            Writing...

    */

8. 类的继承

在 Swift 环境中, 继承是类特有的, 结构体和枚举中不存在继承

当一个类继承其他类的时候, 继承类就被称为子类, 被继承类被称为父类

继承有以下的优点 :

    • 继承是在一些通用的基础上构造, 建立和扩充新类的最有效手段
    • 继承简化了人们对事物的认识和描述, 能清晰体现相关类之间的层次结构关系
    • 继承提供了软件复用功能 : 若 B 类继承 A 类, 那么建立 B 类的时候只需要再描述与 A 类不同的属性和方法即可. 这样的做法减小了代码的冗余度, 增加程序的复用性
    • 继承通过增加一致性, 来减少模块间的借口和界面, 大大增加了程序的易维护性

继承的过程中, 需要重写的方法需要在方法前面增加 override 关键字

当不希望父类的属性, 下标脚本或者方法被重写的时候, 可以在相关属性或者方法前面增加 final 关键字

当继承的类中尝试重写父类方法的时候, 重写方法前面没有添加 override 关键字, 或者尝试重写父类中带有 final 关键字的方法, 属性或者下标脚本的时候, 编译器都会报错

class cAnimal {

    func say() {

        print("I'm an animal!")

    }

}

class cDog : cAnimal {

    var name : String

    init(name : String) {

        self.name = name

    }

    override func say() {

        print("I'm a dog, my name is \(name)!")

    }

}

var dog = cDog(name : "Nano")

dog.say()    //结果 : I’m a dog, my name is Nano!

当子类需要在子类的方法中继承父类相对应的方法, 可以在方法中直接调用父类的相对应的方法, 并且在前面添加 super 关键字

class cCreature {

    var name : String

    init(name : String) {

        self.name = name

    }

    func printName() {

        print(name)

    }

}

class cDog : cCreature {

    var master : String

    init(name : String, master : String) {

        self.master = master

        super.init(name : name)

    }

    override func printName() {

        super.printName()

        print(master)

    }

}

let creature = cDog(name : John, master : Jonny)

creature.printName()

    /*

        结果 :

            John

            Jonny

    */

9. 类的延迟加载

Swift 中, 延迟加载属性表示当第一次被调用的时候, 才会对其进行初始化操作的属性

当某个属性需要延迟加载的时候, 需要在属性前面增加 lazy 关键字, 此时, 只有当需要使用该属性的时候, 才会对该属性进行初始化操作, 从而提供程序的运行效率

class cAvarta {

    var photo : String = "http://www.jonny.vip/avarta/pic1.jpeg"

    init() {

        print("对类 cAvarta 进行了初始化操作")

    }

}

class cUser {

    var name : String = "Jonny"

    lazy var avarta : cAvarta = cAvarta()

    init() {

        print("对类 cUser 进行了初始化操作\n")

    }

}

let user = cUser()

print(user.avarta.photo)

    /*

        结果 :

            对类 cUser 进行了初始化操作

            对类 cAvarta 进行了初始化操作

            http://www.jonny.vip/avarta/pic1.jpeg

    */

10. 类的引用特征

在 Swift 环境中, 元组, 枚举和结构体属于值类型, 而类属于引用类型

值类型最基本的特征就是复制在赋值, 初始化和传递参数过程中的数据, 并为这个数据创建一个崭新和独立的实例

与值类型不同, 引用类型的实例在被赋予到一个变量或常量, 或者作为参数被传递到一个函数时, 其操作的并不是类实例的拷贝, 而是已存在的实例本身

class cAnimal {

    var name : String = "Tiger"

}

let tiger = cAnimal()

print(tiger.name)

let lion = tiger

lion.name = "Lion"

print(tiger.name)

print(lion.name)

    /*

        结果 :

            Tiger

            Lion

            Lion

    */

11. 类型检查

类型检查在 Swift 中是一种检查实例类型的方式, 同时也是让实例作为它的父类或者子类的一种方式

is 操作符 : 对类型进行检查

class cCreature {

    var name : String

    init(name : String) {

        self.name = name

    }

}

class cDog : cCreature {

    var master : String

    init(name : String, master : String) {

        self.master = master

        super.init(name : name)

    }

}

class cBird : cCreature {

    var food : String

    init(name : String, food : String) {

        self.food = food

        super.init(name : name)

    }

}

let creatures : [cCreature] = [

    cDog(name : "Nano", master : "John"),

    cBird(name : "Max", food : "Bugs"),

    cDog(name : "Bailey", master : "Smith"),

    cBird(name : "Charlie", food : "Spider"),

    cDog(name : "Toby", master : "Bill")

]

var dogCount = 0

var birdCount = 0

for item in creatures {

    if item is cDog {

        dogCount += 1

    }

    if item is cBird {

        birdCount += 1

    }

}

print(dogCount)

print(birdCount)

    /*

        结果 :

            3

            2

    */

as 操作符 : 对量进行类的赋值

as 后面的问号 ?as 之间不能有空格

class cCreature {

    var name : String

    init(name : String) {

        self.name = name

    }

}

class cDog : cCreature {

    var master : String

    init(name : String, master : String) {

        self.master = master

        super.init(name : name)

    }

}

class cBird : cCreature {

    var food : String

    init(name : String, food : String) {

        self.food = food

        super.init(name : name)

    }

}

let creatures : [cCreature] = [

    cDog(name : "Nano", master : "John"),

    cBird(name : "Max", food : "Bugs"),

    cDog(name : "Bailey", master : "Smith"),

    cBird(name : "Charlie", food : "Spider"),

    cDog(name : "Toby", master : "Bill")

]

for item in creatures {

    if let dog = item as? cDog {

        print("Dog : \(dog.name), belongs to \(dog.master).")

    }

    if let bird = item as? cBird {

        print("Bird : \(bird.name), loves \(bird.food).")

    }

}

    /*

        结果 :

        Dog : Nano, belongs to John.

        Bird : Max, loves Bugs.

        Dog : Bailey, belongs to Smith.

        Bird : Charlie, loves Spider.

        Dog : Toby, belongs to Bill.

    */

12. AnyAnyObject

Swift 为不确定的类型提供了两种特殊类型别名 : AnyObjectAny

AnyObject 可以代表任何 class 类型的实例, AnyClass 只是 AnyObject 的别名

Any 则可以表示任何类型, 除了方法类型

Any :

var anythings = [Any]()

anythings.append(8)

anythings.append(3.14)

anythings.append("hello")

anythings.append((3.0, 4.0))

for item in anythings {

    switch item {

        case let someInt as Int :

            print("An integer value of \(someInt).")

        case let someDouble as Double :

            print("A double value of \(someDouble).")

        case let someString as String :

            print("A string value of \(someString).")

        case let (x,y) as (Double, Double) :

            print("An (x, y) value of \(x, y).")

        default :

            print("Something else!")

    }

}

    /*

        结果 :

            An integer value of 8.

            A double value of 3.14.

            A string value of hello.

            An (x,y) value of (3.0, 4.0).

    */

AnyObject (AnyClass) :

var anythings = [AnyObject]()

//var anythings = [AnyClass]()

class cDog {

    var name : String = "Unknown"

    init(name : String) {

        self.name = name

    }

}

anythings.append(cDog(name : "John"))

anythings.append(cDog(name : "Smith"))

var dogCount = 0

for item in anythings {

    if item is cDog {

        dogCount += 1

    }

}

print(dogCount)    //结果 : 2