• 构造方法

实例对象在被创建时,需要对存储属性初始化,两种方式:

     方法一:在声明属性的同时设定初值(之前一直使用这种方式)

     方法二:使用构造方法

构造方法init:在对象创建时自动调用并对实例对象的存储属性进行初始化

     a. 无需func关键字声明

     b. 参数列表里可以有多个参数,也可以没有参数,参数可以有默认值

     c. 支持重写和重载

     d. 没有返回值

     如:

    class Person{
       
var name:String
       
var age:Int
       
init(name:String, age:Int) {
           
self.name = name
           
self.age = age
        }
       
init(name1:String) {
           
self.name = name1
           
self.age = 11
        }
       
init(name2:String) {
           
self.name = name2
           
self.age = 12
        }
       
init() {
           
self.name = "123"
           
self.age = 20
        }
    }
   
var p1:Person = Person()
   
print("name:\(p1.name) age:\(p1.age)")//name:123 age:20
    var p2:Person = Person(name1: "iOS")
   
print("name:\(p2.name) age:\(p2.age)")//name:iOS age:11
    var p3:Person = Person(name2: "iOS")
   
print("name:\(p3.name) age:\(p3.age)")//name:iOS age:12
    var p4:Person = Person(name: "iPhone", age: 7)

    print("name:\(p4.name) age:\(p4.age)")//name:iPhone age:7

     init()方法是强制包含外部参数名的,即使未显式写出,也是有的,相当于参数名前有#,可以使用 _ 关闭这个强制功能

     这里有四个重载的init()方法,其中有两个方法仅仅外部参数名不同,也可以进行重载(普通函数不可以)

     

构造方法中的常量:

     常量属性,在构造方法内部是可以变的,即构造方法执行后才是真正的常量

     注意:子类的构造方法不能修改父类常量属性的值


  • 构造方法的分类

默认构造方法:适用于类、结构体、枚举

     当所有的存储属性都有默认值时由系统自动生成

     如果存储属性是一个可选类型,则不必设置默认值也能具有默认构造方法,其默认值为nil

指定构造方法:显式地写出并且可重载,需要为每个存储属性初始化

便捷构造方法:内部调用其他构造方法

     需要在init()前加convenience关键字声明

     只有在便捷构造方法中可以显式调用构造方法,如:

     convenience init() {

          self.init(name:"123", age:20)

     }

可失败构造方法:在某些情况下构造对象失败后,返回nil

     返回nil,意味着返回值类型是一个可选类型,语法:init?()

     可失败构造方法可以声明为便捷构造方法

     如:

     convenience init?(age:Int) {

          self.init(name:"123", age:age)

          if ( age < 0 ) {

               return nil

          }

     }

     var p1:Person? = Person(age: 5)

     隐式解绑的可失败构造方法,即返回值是解绑后的,语法init!()

          也就意味着返回值不再是一个可选类型,也就意味着可失败构造方法返回nil程序会崩溃


  • 继承中的构造过程

先来看一段代码:

    class Animal {
       
var age:Int
       
init() {
           
self.age = 10
           
print("Animal init.")
        }
    }
   
class Dog:Animal {
       
var name:String
       
override init() {
           
self.name = "abc"
           
print("Dog init.")
        }
    }
   
var p = Dog()

    print("age:\(p.age) name:\(p.name)")

     输出的结果:

          Dog init.

          Animal init.

          age:10 name:abc

     重要说明:子类的构造方法一定调用了父类的构造方法完成父类部分的初始化

父子类构造方法的调用顺序:

     上面例子中,在子类的init()中并没有显式调用,则父类的init()实在子类init()的最后隐式调用

     存在的问题是:在子类的init()中不能访问父类的属性

     解决方法:子类的init()中显式调用父类构造方法     

        override init() {
           
self.name = "abc"
           
super.init()
           
self.age++
           
print("Dog init.")

        }

     需要注意的是:显式调用父类构造方法,必须在子类存储属性初始化后进行

子类也可以添加构造方法,子类构造方法内部也可以指定调用其他构造方法

    class Animal {
       
var age:Int
       
init() {
           
self.age = 10
        }
       
init(age:Int) {
           
self.age = age
        }
    }
   
class Dog:Animal {
       
var name:String
       
override init() {
           
self.name = "abc"
           
super.init()
           
self.age++
        }
       
init(age:Int, name:String) {
           
self.name = name
           
super.init(age: age)
        }
       
    }
   
var p = Dog(age: 22, name: "ABC")

    print("age:\(p.age) name:\(p.name)")


  • 析构方法

与构造方法相反,对象即将被销毁前,会自动调用析构方法

     a. 析构方法 deinit 不带任何参数也没有返回值,不用func修饰

     b. 有默认析构方法,也可以显式写出代替

     c. 析构方法不能重载

     d. 子类实例对象销毁时,先调用子类的析构方法,再调用父类的析构方法

     e. 任何位置都不能显式调用deinit

    class Animal {
       
var age:Int
       
init() {
           
self.age = 10
        }
       
init(age:Int) {
           
self.age = age
        }
       
deinit {
           
print("Animal deinit.")
        }
    }
   
class Dog:Animal {
       
var name:String
       
override init() {
           
self.name = "abc"
           
super.init()
           
self.age++
        }
       
init(age:Int, name:String) {
           
self.name = name
           
super.init(age: age)
        }
       
deinit {
           
print("Dog deinit")
        }
    }
   
var p = Dog(age: 22, name: "ABC")

    print("age:\(p.age) name:\(p.name)")

    p = Dog()     //基于ARC机制,此时上一个Dog实例对象被销毁

     输出结果:

          age:22 name:ABC

          Dog deinit

          Animal deinit.