Swift:面向对象(继承与构造方法)

前端之家收集整理的这篇文章主要介绍了Swift:面向对象(继承与构造方法)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

一、 继承

1. Swift中定义的类,如果不继承自任何类,它就是基类。这一点和objective-c中定义的类不一样,在objective-c中定义的类默认的基类是NSObject。
2. 重写父类方法属性,必须使用override的关键字(这样处理的话,更清晰了,很容易看出是父类方法还是自己类中的方法)。
3. 如果在类,方法属性 前面用final进行了修饰,就不允许被继承或者被重写。

类继承关系Demo:

  1. class Animal {
  2. var speed : Int = 1
  3. func run() {
  4. println("Animal is running")
  5. }
  6. }
  7.  
  8. class Dog: Animal {
  9. override var speed : Int {
  10. get {
  11. return super.speed
  12. }
  13. set {
  14. if newValue > 100 {
  15. super.speed = 100
  16. } else {
  17. super.speed = newValue
  18. }
  19. }
  20. }
  21. override func run() {
  22. println("Dog is running")
  23. }
  24. }

二、 构造方法

在Swift中,存储属性在定义的时候必须要进行初始化工作,这一点我在Swift:面向对象(属性)中有提到过。如果不进行初始化的话,我们也可以在构造方法中完成初始化工作。

Swift中构造方法的特点:

1. 方法名字叫做init。

2. 没有func关键字。

3. 没有返回值。

Demo:

  1. class Person {
  2. var name: String
  3. var age: Int
  4. init(name: String,age: Int) {
  5. self.name = name
  6. self.age = age
  7. }
  8. }
  9.  
  10. var p = Person(name: "Rose",age: 30)

在本例中,有两个存储属性name和age,它们在定义的时候均没有完成初始化工作,但我们可以在init(name: String,age: Int) 这个构造方法中完成它们的初始化工作。self.name 和 self.age 就是定义的两个属性,而 name 和 age 就是外界传递过来的变量值。

三、 指定构造方法(Designated) 和 便利构造方法(Convenience

关于指定构造方法和便利构造方法的使用有很多规则。

1.只有便利构造方法才能调用当前类的其他构造方法

  1. class Person {
  2. var name: String
  3. var age: Int
  4. init(name: String,age: Int) {
  5. self.name = name
  6. self.age = age
  7. }
  8. init(name: String) {
  9. self.init(name: name,age: 10)
  10. }
  11. }

在上例中,试图在init(name: String) 这个构造方法调用init(name: String,age: Int)这个构造方法,并且age的默认值是10。但是程序会直接报错。


可以看出,错误信息很明显,提示你在init(name: String) 构造方法之前加上convenience,使这个构造方法变成便利构造方法即可。

2. 只有指定构造方法才能调用父类的构造方法

  1. class Person {
  2. var name: String
  3. var age: Int
  4. init(name: String,age: Int) {
  5. self.name = name
  6. self.age = age
  7. }
  8. convenience init(name: String) {
  9. self.init(name: name,age: 10)
  10. }
  11. }
  12.  
  13. class Jack: Person {
  14. convenience init(name: String) {
  15. super.init(name: name,age: 20)
  16. }
  17. }

上例中,试图在Jack这个子类的 convenience init(name: String) 这个便利构造方法调用父类Person的指定构造方法init(name: String,age: Int)。但是程序会报错。


所以,我们将Jack这个类中的convenience这个关键字去掉即可。让子类的直接构造方法调用父类的直接构造方法

3. 有参的指定构造方法会覆盖调用默认的无参指定构造方法

在Swift中定义的类中,都有一个默认的无参指定构造方法,只是没有显示出来。例如:

  1. class Person {
  2. }

它其实有一个 init(){} 指定构造方法,这也是为什么可以书写下面的代码完成对象的初始化工作。
  1. var p = Person()

但是,如果你在代码中书写了有参指定构造方法,那么默认的无参指定构造方法将被覆盖掉。例如:
  1. class Person {
  2. var name: String
  3. var age: Int
  4. init(name: String,age: Int) {
  5. self.name = name
  6. self.age = age
  7. }
  8. }

此时你再调用
  1. var p = Person()
这句代码将直接报错了。


但如果想不管调用无参构造方法还是有参构造方法都可以。那么你将默认的指定都早方法写出来即可。

  1. class Person {
  2. var name: String
  3. var age: Int
  4. init() {
  5. self.name = "rose"
  6. self.age = 20
  7. }
  8. init(name: String,age: Int) {
  9. self.name = name
  10. self.age = age
  11. }
  12. }

此时你调用如下代码,是完全可以的。
  1. var p = Person()
  2. var p2 = Person(name: "tick",age: 20)
4. 如果父类中存在有参的指定构造方法,子类的指定构造方法不会自动调用父类无参的指定构造方法
  1. class Person {
  2. var name: String
  3. var age: Int
  4. init(name: String,age: Int) {
  5. self.name = name
  6. self.age = age
  7. }
  8. }
  9.  
  10. class Jack: Person {
  11. override init(name: String,age: Int) {
  12. super.init()
  13. }
  14. }

子类Jack的构造方法调用父类的init默认无参的构造方法,将会直接报错。


所以我们在子类的构造方法中可直接调用父类的有参构造方法即可,代码如下:

  1. super.init(name: name,age: age)

5. 常量属性只能在定义它的类的构造方法中初始化,不能在子类中初始化。

  1. class Person {
  2. var name: String
  3. var age: Int
  4. let gender: String
  5. init(name: String,age: Int,gender: String) {
  6. self.name = name
  7. self.age = age
  8. self.gender = gender
  9. }
  10. }
  11.  
  12. class Jack: Person {
  13. override init(name: String,gender: String) {
  14. self.age = 10
  15. self.gender = "W"
  16. super.init(name: name,age: age,gender: gender)
  17. }
  18. }

注意到在Person中定义的gender是一个常量,所以我试图在子类中对其进行初始化,是失败的。错误信息。



关于构造方法的知识,开起来似乎有点复杂,我们也可以分析下面两站流程图来分析上面我所提到的知识点。




四、 析构方法

Swift中的析构方法类似于objective-c中的dealloc的处理。

Demo:

  1. class Dog {
  2. deinit {
  3. println("Dog Die")
  4. }
  5. }
  6.  
  7. func oneDog() {
  8. var d = Dog()
  9. }
  10.  
  11. println("New Dog")
  12. oneDog()
  13. println("Game Over")

oneDog函数执行完毕后,d变量被销毁,Dog对象就失去了强引用,也就被销毁了,会调用析构方法deinit

最终打印结果
"New Dog"
"Dog Die"
"Game Over"

注:一个对象被释放前,先自动调用自己的析构方法,然后一层一层往上调用父类的析构方法

猜你在找的Swift相关文章