本文参考内容:Swift 3.0更新说明
构造过程与析构过程,类似与OC中的alloc
与dealloc
,一生成一释放,所以放在一起写
-
构造过程
-
属性默认值:
-
我们定义类的属性时,必须为每个属性设置默认值,否则会报错,可选类型的属性,若我们不进行赋值,也有一个默认值nil
class SomeClass { var num = 0 }
- ####构造器:
Swift中,类,结构体或者枚举提供了构造方法init
,每当实例化对象时,都会默认调用此方法
class SomeClass { var num:Int init() { num = 3 print("init") } } var someClass = SomeClass()
- ####自定义构造器:
Swift中,我们可以通过修改init方法中的传入参数,达到自定义构造器的效果.注意传入参数必须拥有标签名来区分对应的init方法,同样你也可以使用关键字_
来忽略传入参数名称.
class SomeClass { var num:Int init(num:Int) { self.num = num print("init") } init(_ num:Int) { self.num = num } } var someClass = SomeClass(num: 3) var anotherClass = SomeClass(3)
- 如果类的属性为不为可选类型,如果未在"init"方法中对属性进行赋值,且在定义属性时也没有赋予默认值.可选类型之所以不报错,是因为它有一个默认值nil
class SomeClass { var num:Int var numPlusThree:Int? init(num:Int) { self.num = num print("init") } func plus() -> Int { numPlusThree = num + 3 return numPlusThree! } } var someClass = SomeClass(num: 3) someClass.plus()
- ####默认构造器:
Swift中,如果结构体或类都有默认值,则编译器会隐式的增添一个构造器为所有属性设置默认值.若结构体中没有为属性设置默认值,我们可以在生成实例时使用它的逐一成员构造器
//定义一个拥有默认值的结构体,使用默认构造器生成实例 struct SomeStruct { var a:Int = 1 var b:Int = 2 } var someStruct = SomeStruct() //定义一个拥有默认值的结构体,使用逐一构造器生成实例 struct AnotherStruct { var a:Int var b:Int } var anotherStruct = AnotherStruct(a: 2, b: 3) //定义一个拥有默认值的类,使用默认构造器生成实例 class SomeClass { var a = 1 var b = 2 } var someClass = SomeClass()
- ####可失败构造器:
Swift中,提供了一种可以构造失败的构造器.
- 当构造器传入无效参数,或者缺少某种外部资源,或者不满足某个条件等,我们可失败构造器中返回"nil"对象来代替实例,但当成功的时候,我们不能返回任何东西
- 使用init?
来创建可失败构造器,注意,可失败构造器与普通构造器的传入参数不可相同
- 我们可以重写可失败构造器,并把他改成普通构造器.但我们不能通过重写,把普通构造器改成可失败构造器
class NumberGreatterThanZero { var number:Int init() {} init?(num:Int) { if num <= 0 { return nil } else { number = num } } } class SubNumber : NumberGreatterThanZero{ override init(num:Int) { super.init() if num < 1 { number = 0 }else { number = num } } } var superNum = NumberGreatterThanZero(num:0)//返回nil var subNum = SubNumber(num:0)//返回实例 var number = NumberGreatterThanZero(num: 0) if number == nil { print("init fail") }
- ####必要构造器:
Swift中,在父类的构造器方法前添加required
关键字,来强制要求所有的子类必须实现该构造器
class SomeClass { var name:String required init() { name = "name" } } class SomeSubclass: SomeClass { required init() { super.init() name = "subName" } }
- 枚举中,自动拥有init?(rawValue)
的隐藏可失败构造器,前提是该枚举必须设置了原始值
enum Number:Int { case one = 1 case two,three,four } var one = Number(rawValue: 1) var five = Number(rawValue: 5)
- ####构造器代理:
Swift中,构造器可以通过调用其它构造器来完成实例的部分构造过程,这一过程称为结构器代理.在构造器中,使用self.init
可以调起其他构造器方法
struct AnotherStruct { var a:Int var b:Int init(a:Int,b:Int) { self.a = a self.b = b } init (num:Int) { self.init(a:num,b:num+3) } } var anotherStruct = AnotherStruct(num: 3) print(anotherStruct.a,anotherStruct.b)
-
类的继承和构造过程
-
指定构造器和便利构造器
-
指定构造器:
-
-
Swift中,指定构造器是类中最主要的构造器,一个指定构造器将初始化类中提供的所有属性,并根据父类链往上调用父类的构造器来实现父类的初始化。置顶构造器的写法与上述的方法相同
init(parameters) { statements }
- #####便利构造器:
Swift中,便利构造器是次要的构造器,一般用来调起同类中的某个指定构造器,或者创建某个特殊的实例.使用关键字convenience
convenience init(parameters) { statements }
- #####类的构造器代理规则
- 指定构造器必须调用其直接父类的指定构造器
- 便利构造器只能调用同类中的构造器,且最终必须调起一个指定构造器.
- ####两段式构造过程:
Swift中,类的构造过程包含两个阶段。第一个阶段,每个存储型属性被引入它们的类指定一个初始值。当每个存储型属性的初始值被确定后,第二阶段开始,它给每个类一次机会,在新实例准备使用之前进一步定制它们的存储型属性。
- #####阶段 1
- 某个指定构造器或便利构造器被调用。
- 完成新实例内存的分配,但此时内存还没有被初始化。
- 指定构造器确保其所在类引入的所有存储型属性都已赋初值。存储型属性所属的内存完成初始化。
- 指定构造器将调用父类的构造器,完成父类属性的初始化。
- 这个调用父类构造器的过程沿着构造器链一直往上执行,直到到达构造器链的最顶部。
- 当到达了构造器链最顶部,且已确保所有实例包含的存储型属性都已经赋值,这个实例的内存被认为已经完全初始化。此时阶段 1 完成。
- #####阶段 2
- 从顶部构造器链一直往下,每个构造器链中类的指定构造器都有机会进一步定制实例。构造器此时可以访问self、修改它的属性并调用实例方法等等。
- 最终,任意构造器链中的便利构造器可以有机会定制实例和使用self。
- ####构造器的继承与重写:
Swift中,子类可以重写父类的指定构造器,使用override
关键字,Swift中,当添加了该关键字,Swift会自动检查该类父类是否有对应的指定构造器,并验证参数.
注意,调用前需要确定子类中的所有属性必须有初始值
从上述的构造代理规则,以及两段式构造过程可以看出,子类重写父类的指定构造器时,须等待父类完成构造.
此时才能对子类中的属性进行操作,方法进行调用.所以,我们在下面列子中,必须先调用super.init()
.
```
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
class Bicycle: Vehicle {
var number : Int
override init() {
number = 0
super.init()
numberOfWheels = 2
}
}
```
- 构造器的自动继承
- 规则 1
如果子类没有定义任何指定构造器,它将自动继承所有父类的指定构造器。
- 规则 2
如果子类提供了所有父类指定构造器的实现——无论是通过规则 1 继承过来的,还是提供了自定义实现——它将自动继承所有父类的便利构造器。
-
析构过程:
Swift中,生成实例时会有对应的构造器,那么对象释放时,也有对应的析构器,每个类只有一个析构器,deinit
方法,该方法无法被主动调用,只有在对象释放时自动调用
class Deinit {
deinit {
print("类已经被释放")
}
}
var dein : Deinit? = Deinit()
dein = nil