类¶
1. 类的创建¶
类是属于用户自定义的数据类型,并且该类型具有一定的行为能力,也就是类中所描述的方法。 通常来说,一个类的定义包含两部分内容,一部分是该类的属性,另一部分是它所拥有的方法。以汽车这个类来说,每种车都有自己的品牌,车龄,出厂日期,耗油量的等属性,此外汽车还拥有启动,刹车,转弯,倒车等属于汽车所具有的行为。 和定义枚举和结构体类似,在定义类的时候,使用class作为关键字,并把类的具体内容放置在一对大括号中。
1 2 3 4 5 | class 类名
{
//属性方法
//方法列表
}
|
以汽车形象为样本,创建一个汽车类。
1 2 3 4 5 | class Car { var brand: String = "" var speed: Int = 0 } |
在上记代码中,使用class关键字定义了一个名为Car的类,它拥有brand和speed两个属性。Swift要求在定义类时,类的属性要进行初始化,所以这里设置brand属性的默认值为空的字符串,而speed属性的默认值为0。
其中可以在定义类的时候,给它指定自定义的init初始化方法。
1 2 3 4 5 6 7 8 9 10 11 | class Car { var brand: String var speed: Int init() { self.brand = "" self.speed = 0 } } |
2. 类属性的set和get方法¶
了解java的同学都应该知道,在类中可以对属性进行set和get设置。在Swift中同样可以对类属性进行set和get设定操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class Hero { var damage : Int = 10 // 伤害 var level : Int // 级别 { get { return self.damage/10 } set(newLevel) { self.damage = newLevel * 10 } } } |
3. 类属性的willSet和didSet方法¶
通过给属性添加willSet和didSet方法,可以给类添加属性观察者。属性观察者可以观察属性值得改变,并对此做出相应的反应。当设置属性的之时,属性观察者就被调用,即使新值和原值相同时也会被调用。 可以单独或同时使用下面的两个方法,以进行属性观察者的定义:willSet方法在设置属性值之前调用,而didSet方法则在设置属性值之后被调用。 当实现willSet观察者时,新的属性值作为常量参数被传递。可以为这个参数起一个名字,如果不命名,则这个参数就被默认命名为 newValue。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class Hero { var damage: Int = 10 var level: Int = 1 { willSet { print("level的新值=\(newValue)") } didSet { if(oldValue < level) { print("英雄升级!") } else { print("挑战失败,未能升级!") } } } } let hero = Hero() hero.level = 2 hero.level = 2 |
在上面的代码中,level属性进行了两次赋值set操作,所以willSet和didSet方法都被调用了两次,在控制台的最终结果如下所示:
1 2 3 4 | level的新值=2 英雄升级! level的新值=2 挑战失败,未能升级! |
4. 类的静态方法¶
在移动开发项目中,你会经常发现在一些工具类中,定义了大量的静态方法。如果某些操作不依赖具体实例,那它就是静态的,你可以将方法定义为静态方法。反之如果某些操作是依赖具体实例的,那它就应该实例化的。 在Swift环境中,可以为类,结构体和枚举等类型等类型定义静态方法,也称为类型方法。在为结构体和枚举定义静态方法时,可以使用 static 关键字;在为类定义静态方法时,可以使用 class 关键字。
注意:使用class关键字声明的静态方法,在子类中可以被覆写
5. 类的析构¶
Swift和Objective-C一样是通过自动引用计数(ARC)技术,来实现对实例的内存管理的。Swift会自动释放不再需要的实例以释放资源。所以当你的实例被释放时,不需要手动去清理。 但是,当释放程序中的资源时,你可能需要额外进行一些清理。例如:如果你创建了一个自定义的类来打开文件,并写入若干数据,就需要在类实例被释放之前关闭该文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class FileManager { func loadFile() { print("加载文件") } func writeFile() { print("写文件") } deinit() { print("关闭文件") } } |
如果创建了名为fileManager的实例,最后将fileManager的实例设置为 nil。系统就会自动调用析构函数。
6. 类的继承¶
在Swift中,类可以调用和访问父类的方法,属性和下标脚本,也可以重写他们。 在使用继承功能之前,创建一个基类,即没有继承其他类的类:
1 2 3 4 5 6 7 | class Animal { func say() { print("I'm an animal.") } } |
这里定义了一个名为Animal的基类,它拥有一个名为say的方法。接着定义一个继承自Animal的子类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | class Dog : String { var name: String init(name: String) { self.name = name } override func say() { print("I'm dog, my name is \(name)") } } |
如果不希望父类的属性,下标或方法被重写,它们之前添加final修饰符。
7. 类的延迟加载属性¶
延迟加载属性是指当第一次被调用的时候,才会对其进行初始化操作的属性。 当一个类拥有一个重度且不经常使用的属性时,比如该属性是一个复杂的类,或者属性在初始化时需要从本地或网络加载所需的资源。此时在属性声明前使用lazy关键词,可将该属性标示为一个延迟加载属性,这样只有在使用到该属性时,才会对该属性进行初始化操作,从而提高程序的运行效率。
1 2 3 4 5 6 7 8 9 10 11 12 | class A { var photo: UIImage = UIImage(named: "pic1")! } class B { lazy var a: A = A() } let b = B() print(b.a.photo) |