一、 继承
1. Swift中定义的类,如果不继承自任何类,它就是基类。这一点和objective-c中定义的类不一样,在objective-c中定义的类默认的基类是NSObject。
2. 重写父类的方法及属性,必须使用override的关键字(这样处理的话,更清晰了,很容易看出是父类的方法还是自己类中的方法)。
3. 如果在类,方法,属性 前面用final进行了修饰,就不允许被继承或者被重写。
类继承关系Demo:
- class Animal {
- var speed : Int = 1
- func run() {
- println("Animal is running")
- }
- }
- class Dog: Animal {
- override var speed : Int {
- get {
- return super.speed
- }
- set {
- if newValue > 100 {
- super.speed = 100
- } else {
- super.speed = newValue
- }
- }
- }
- override func run() {
- println("Dog is running")
- }
- }
二、 构造方法
在Swift中,存储属性在定义的时候必须要进行初始化工作,这一点我在Swift:面向对象(属性)中有提到过。如果不进行初始化的话,我们也可以在构造方法中完成初始化工作。
Swift中构造方法的特点:
1. 方法名字叫做init。
2. 没有func关键字。
3. 没有返回值。
Demo:
- class Person {
- var name: String
- var age: Int
- init(name: String,age: Int) {
- self.name = name
- self.age = age
- }
- }
- var p = Person(name: "Rose",age: 30)
在本例中,有两个存储属性name和age,它们在定义的时候均没有完成初始化工作,但我们可以在init(name: String,age: Int) 这个构造方法中完成它们的初始化工作。self.name 和 self.age 就是定义的两个属性,而 name 和 age 就是外界传递过来的变量值。
三、 指定构造方法(Designated) 和 便利构造方法(Convenience)
- class Person {
- var name: String
- var age: Int
- init(name: String,age: Int) {
- self.name = name
- self.age = age
- }
- init(name: String) {
- self.init(name: name,age: 10)
- }
- }
在上例中,试图在init(name: String) 这个构造方法中调用init(name: String,age: Int)这个构造方法,并且age的默认值是10。但是程序会直接报错。
可以看出,错误信息很明显,提示你在init(name: String) 构造方法之前加上convenience,使这个构造方法变成便利构造方法即可。
- class Person {
- var name: String
- var age: Int
- init(name: String,age: Int) {
- self.name = name
- self.age = age
- }
- convenience init(name: String) {
- self.init(name: name,age: 10)
- }
- }
- class Jack: Person {
- convenience init(name: String) {
- super.init(name: name,age: 20)
- }
- }
上例中,试图在Jack这个子类的 convenience init(name: String) 这个便利构造方法中调用父类Person的指定构造方法init(name: String,age: Int)。但是程序会报错。
所以,我们将Jack这个类中的convenience这个关键字去掉即可。让子类的直接构造方法调用父类的直接构造方法。
在Swift中定义的类中,都有一个默认的无参指定构造方法,只是没有显示出来。例如:
- class Person {
- }
它其实有一个 init(){} 指定构造方法,这也是为什么可以书写下面的代码完成对象的初始化工作。
- var p = Person()
但是,如果你在代码中书写了有参指定构造方法,那么默认的无参指定构造方法将被覆盖掉。例如:
- class Person {
- var name: String
- var age: Int
- init(name: String,age: Int) {
- self.name = name
- self.age = age
- }
- }
此时你再调用
这句代码将直接报错了。
- var p = Person()
但如果想不管调用无参构造方法还是有参构造方法都可以。那么你将默认的指定都早方法写出来即可。
- class Person {
- var name: String
- var age: Int
- init() {
- self.name = "rose"
- self.age = 20
- }
- init(name: String,age: Int) {
- self.name = name
- self.age = age
- }
- }
此时你调用如下代码,是完全可以的。
4. 如果父类中存在有参的指定构造方法,子类的指定构造方法不会自动调用父类无参的指定构造方法。
- var p = Person()
- var p2 = Person(name: "tick",age: 20)
- class Person {
- var name: String
- var age: Int
- init(name: String,age: Int) {
- self.name = name
- self.age = age
- }
- }
- class Jack: Person {
- override init(name: String,age: Int) {
- super.init()
- }
- }
子类Jack的构造方法调用了父类的init默认无参的构造方法,将会直接报错。
所以我们在子类的构造方法中可直接调用父类的有参构造方法即可,代码如下:
- super.init(name: name,age: age)
5. 常量属性只能在定义它的类的构造方法中初始化,不能在子类中初始化。
- class Person {
- var name: String
- var age: Int
- let gender: String
- init(name: String,age: Int,gender: String) {
- self.name = name
- self.age = age
- self.gender = gender
- }
- }
- class Jack: Person {
- override init(name: String,gender: String) {
- self.age = 10
- self.gender = "W"
- super.init(name: name,age: age,gender: gender)
- }
- }
注意到在Person中定义的gender是一个常量,所以我试图在子类中对其进行初始化,是失败的。错误信息。
关于构造方法的知识,开起来似乎有点复杂,我们也可以分析下面两站流程图来分析上面我所提到的知识点。
四、 析构方法
Swift中的析构方法类似于objective-c中的dealloc的处理。
Demo:
- class Dog {
- deinit {
- println("Dog Die")
- }
- }
- func oneDog() {
- var d = Dog()
- }
- println("New Dog")
- oneDog()
- println("Game Over")
oneDog函数执行完毕后,d变量被销毁,Dog对象就失去了强引用,也就被销毁了,会调用析构方法deinit
最终打印结果
"New Dog"
"Dog Die"
"Game Over"