一、 继承
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)
关于指定构造方法和便利构造方法的使用有很多规则。
1. 只有便利构造方法才能调用当前类的其他构造方法。
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, 使这个构造方法变成便利构造方法即可。
2. 只有指定构造方法才能调用父类的构造方法
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这个关键字去掉即可。让子类的直接构造方法调用父类的直接构造方法。
3. 有参的指定构造方法会覆盖调用默认的无参指定构造方法。
在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 } }
此时你调用如下代码,是完全可以的。
var p = Person() var p2 = Person(name: "tick", age: 20)
4. 如果父类中存在有参的指定构造方法,子类的指定构造方法不会自动调用父类无参的指定构造方法。
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, age: Int, 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"
注: 一个对象被释放前,先自动调用自己的析构方法,然后一层一层往上调用父类的析构方法
版权声明:本文为博主原创文章,未经博主允许不得转载。