热门IT资讯网

Swift2.0(13)构造方法

发表于:2024-11-28 作者:热门IT资讯网编辑
编辑最后更新 2024年11月28日,构造方法实例对象在被创建时,需要对存储属性初始化,两种方式:方法一:在声明属性的同时设定初值(之前一直使用这种方式)方法二:使用构造方法构造方法init:在对象创建时自动调用并对实例对象的存储属性进行
  • 构造方法

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

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

方法二:使用构造方法

构造方法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.


0