一、为何要初始化?:
1.系统要求存储属性必须初始化
2.可选值可以不用初始化,如果不初始化值,系统默认用nil初始化它
3.如果非可选类型存储属性不设置默认值,则必须在初始化方法中对其进行初始化
4.类必须自己写初始化方法,初始化没有默认值的非可选存储属性
5.结构体系统默认会添加初始化方法,当然自己也可以自定义
6.子类如果没有自己的初始化方法,系统默认使用父类的初始化方法,一旦有了自己的初始化方法,或者重写了父类的初始化方法,则父类的所有初始化不能被子类调用
7.你可以给子类添加和父类相同的初始化方法,但需要加上override修饰
8.重写父类的convenience修饰的方便初始化方法,不需要加override关键字
二、类初始化的几种方法:
a、指定初始化(Designated)
b、方便初始化(convenience)
1.在同一个类,使用convenience修饰的初始化方法必须调用一个其他初始化方法
2.convenience必须最终调用一个指定的初始化方法
3.当子类继承父类时,子类的初始化方法,必须调用父类的指定初始化方法,不能调用使用convienience修饰的方便初始化方法
4.在swift3.0初始化中,可以自己调用自己的初始化方法,系统不会检测出来,在创建convenience方便初始化方法的时候,需要小心,千万不要相互引用了
c、需要的初始化方法(required)
1.子类必须重写父类用required修饰的方法
2.可以和convenience组合使用
、反初始化(deinit)
1.deinit在对象被释放前调用
三、类初始化的过程:
第一阶段
1.调用指定初始化方法或者方便初始化
2.给新的实例分配内存,但内存还没有初始化
3.指定初始化方法确定所有存储属性都被初始化,内存这个时候被初始化
4.然后去调用父类的指定初始化方法,任务和调用自己指定初始化方法相同
5.继续在类继承链中指定上述过程,直到达到链的顶部为止
6.当到完成基类的初始化的时候,实例的初始化算是完成了,我们的第一阶段完成
第二阶段
1.可以对属性值进行修改
2.可以调用对象方法
四、类初始化的概括:
1.创建新的指定初始化方法,必须调用父类的指定初始化方法(Designated)
2.创建新的方便初始化方法,必须调用自己的指定初始化方法,或者方便初始化方法(convenience)
3.重写父类的指定初始化方法,在方法名前加override ,然后调用父类的指定初始化方法
4.重写父类的方便初始化方法(convenience)不需要加override或者convenience关键字,调用父类的指定初始化方法,如果加上convenice关键字,则必须调用自己的初始化方法
5.如果子类没有初始化方法,系统会自动继承父类的初始化方法
6.初始化调用父类初始化时,需要先初始化子类的存储属性,但是如果是convenience修饰的初始化方法,要先调用自己的其他初始化方法,然后再给自己的存储属性赋值
注意:
1.不能在重写的初始化方法改为可能失败的初始化方法
2.不能使用相同的参数定义一个可能失败的初始化方法和不会失败的初始化方法
3.可能失败的类型可以重写为不会失败类型
4.init?可以被重写为init!,当然可逆也是可以的
5.init?和init!都可以被重写为init
classPerson {
/**------指定初始化(Designated)------*/
classPerson {
varname:String
varage:Int=0
varweight:Double=0.0
varheight:Double=0.0
init(name:String, age:Int,weight:Double,height:Double) {
self.name= name
self.age= age
self.weight= weight
self.height= height
}
init(name:String) {
self.name= name
}
}
/**------方便初始化(convenience)------*/
classPerson2 {
varname:String
varage:Int=0
varweight:Double=0.0
varheight:Double=0.0
init(name:String, age:Int,weight:Double,height:Double) {
self.name= name
self.age= age
self.weight= weight
self.height= height
}
init(name:String) {
self.name= name
}
// 1.定义一个convenience修饰的初始化方法,如果在同一个类中必须调用其他没有convenience修饰的初始化方法
convenienceinit(name:String,age:Int) {
self.init(name: name)
self.age= age
}
// 2.如果定义两个或者多个convenience修饰的初始化,只需要调用任意一个初始化方法即可满足语法要求
convenienceinit(name:String,age:Int,weight:Double){
self.init(name: name,age: age)
self.weight= weight
}
}
//子类
classMan:Person{
varaddress:String=""
//init(name:String,age:Int,weight:Double) {
// 3.必须调用父类指定初始化方法,不能调用convenience修饰的方便初始化方法
//super.init(name: name)
//}
//重写父类指定初始化方法
overrideinit(name:String) {
super.init(name: name)
}
//重写父类convenience修饰的初始化方法不需要添加override关键字
init(name:String,age:Int,weight:Double){
super.init(name: name)
}
//创建自己的初始化方法
convenienceinit(name:String,age:Int,weight:Double,address:String){
self.init(name: name)
self.address= address
self.age= age
self.weight= weight
}
}
classMan2:Person{
varaddress:String=""
//重写父类的初始化方法
convenienceinit?(name:String,age:Int,weight:Double,address:String){
ifname==""{
returnnil
}
self.init(name: name)
self.address= address
self.age= age
self.weight= weight
}
enumTemperatureUnit {
casekelvin, celsius, fahrenheit
init?(symbol:Character) {
switchsymbol {
case"K":
self= .kelvin
case"C":
self= .celsius
case"F":
self= .fahrenheit
default:
returnnil
}
}
}
classAnimal{
varname:String
init?(name:String) {
ifname.isEmpty{
returnnil
}
self.name= name
}
}
enumTemperatureUnit2:Character{
casekelvin ="K", celsius ="C", fahrenheit ="F"
}
//必须进行验证
letfahrenheitUnit =TemperatureUnit(rawValue:"F")
iffahrenheitUnit !=nil{
print("This is a defined temperature unit, so initializationsucceeded.")
}
classDocument {
varname:String?
init?(name:String?){
ifname !=nil&&name!.isEmpty{
returnnil
}
self.name= name
}
}
classDocument2 {
varname:String?
init() {}//专门初始化name为nil的情况
init?(name:String) {//传入名字,肯定不为nil ,只需要判断是否为空即可
ifname.isEmpty{
returnnil
}
self.name= name
}
}
classPerson {
varname:String
varage:Int=0
varweight:Double=0.0
varheight:Double=0.0
init(name:String,height:Double) {
self.name= name
self.height= height
}
init(name:String) {
self.name= name
}
//要求子类必须重写这个方法
requiredconvenienceinit(name:String,age:Int,weight:Double){
self.init(name:name)
self.age= age
self.weight= weight
}
}
classMan3:Person{
varaddress:String=""
//重写父类要求的初始化convenience修饰的初始化方法不需要添加override关键字
requiredinit(name:String,age:Int,weight:Double){
super.init(name: name)
}
}
//例子:有一个赌徒在银行存了10_000元,赌徒从银行取钱然后去赌博,当赌徒对象释放了就将钱全部存到银行
classBank {
staticvarcoinsInBank =10000;
staticfuncdistribute(coins numberOfCoinsRequested:Int) ->Int{
letnumberOfCoinsToVend =min(numberOfCoinsRequested,coinsInBank)
coinsInBank-= numberOfCoinsToVend
returnnumberOfCoinsToVend
}
staticfuncreceive(coins:Int) {
coinsInBank+= coins
}
}
classPlayer {
varcoinsInPurse:Int
init(coins:Int) {
coinsInPurse=Bank.distribute(coins: coins)
}
funcwin(coins:Int) {
coinsInPurse+=Bank.distribute(coins: coins)
}
deinit{
Bank.receive(coins:coinsInPurse)
}
}
varplayerOne:Player? =Player(coins:100)
playerOne!.win(coins:2000)
playerOne =nil