Swift3.0 - 初始化和释放

Swift3.0 - 真的很简单
Swift3.0 - 数据类型
Swift3.0 - Array
Swift3.0 - 字典
Swift3.0 - 可选值
Swift3.0 - 集合
Swift3.0 - 流控制
Swift3.0 - 对象和类
Swift3.0 - 属性
Swift3.0 - 函数和闭包
Swift3.0 - 初始化和释放
Swift3.0 - 协议protocol
Swift3.0 - 类和结构体的区别
Swift3.0 - 枚举
Swift3.0 - 扩展
Swift3.0 - 下标
Swift3.0 - 泛型
Swift3.0 - 异常错误
Swift3.0 - 断言
Swift3.0 - 自动引用计数(strong,weak,unowned)
Swift3.0 - 检测API
Swift3.0 - 对象的标识
Swift3.0 - 注释
Swift3.0 - 元类型
Swift3.0 - 空间命名
Swift3.0 - 对象判等
Swift3.0 - 探究Self的用途
Swift3.0 - 类簇
Swift3.0 - 动态调用对象(实例)方法
Swift3.0 - 文本输出
Swift3.0 - 黑魔法swizzle
Swift3.0 - 镜像
Swift3.0 - 遇到的坑

注意

1.系统要求存储属性必须初始化
2.可选值可以不用初始化,如果不初始化值,系统默认用nil初始化它
3.如果非可选类型存储属性不设置默认值,则必须在初始化方法中对其进行初始化
4.类必须自己写初始化方法,初始化没有默认值的非可选存储属性
5.结构体系统默认会添加初始化方法,当然自己也可以自定义
6.子类如果没有自己的初始化方法,系统默认使用父类的初始化方法,一旦有了自己的初始化方法,或者重写了父类的初始化方法,则父类的所有初始化不能被子类调用
7.你可以给子类添加和父类相同的初始化方法,但需要加上override 修饰
8.重写父类的convenience修饰的方便初始化方法,不需要加override 关键字

  • 指定初始化(Designated)

1.可以有多个指定初始化方法

class Person{
var name:String
var age:Int = 0
var weight:Double = 0.0
var height:Double = 0.0
init(name:String,height:Double) {
    self.name = name
    self.height = height
}
init(name:String) {
    self.name = name
}
}
  • 方便初始化(convenience)

记住:

1.在同一个类,使用convenience修饰的初始化方法必须调用一个其他初始化方法
2.convenience 必须最终调用一个指定的初始化方法
3.当子类继承父类时,子类的初始化方法,必须调用父类的指定初始化方法,不能调用使用convienience修饰的方便初始化方法
4.在swift3.0 初始化中,可以自己调用自己的初始化方法,系统不会检测出来,在创建convenience方便初始化方法的时候,需要小心,千万不要相互引用了

看图理解更透彻

实例代码

// 父类
class Person{
    var name:String
    var age:Int = 0
    var weight:Double = 0.0
    var height:Double = 0.0
    init(name:String,height:Double) {
        self.name = name
        self.height = height
    }
    init(name:String) {
        self.name = name
    }
    // 1.定义一个convenience 修饰的初始化方法,如果在同一个类中必须 调用其他没有convenience修饰的初始化方法
    convenience init(name:String,age:Int){
        self.init(name:name)
        self.age = age
    }
    // 2.如果定义两个或者多个convenience 修饰的初始化,只需要调用任意一个初始化方法即可满足语法要求
    convenience init(name:String,age:Int,weight:Double){
        self.init(name:name,age:age)
        self.weight = weight
    }
}
// 子类
class Man: Person {
    var address:String = ""
    init(name:String,age:Int,weight:Double) {
         // 3.必须调用父类指定初始化方法,不能调用convenience 修饰的方便初始化方法
         super.init(name: name)
    } 
}
看完代码这种图就好理解了
  • 类初始化的过程

第一阶段

1.调用指定初始化方法或者方便初始化
2.给新的实例分配内存,但内存还没有初始化
3.指定初始化方法确定所有存储属性都被初始化,内存这个时候被初始化
4.然后去调用父类的指定初始化方法,任务和调用自己指定初始化方法相同
5.继续在类继承链中指定上述过程,直到达到链的顶部为止
6.当到完成基类的初始化的时候,实例的初始化算是完成了,我们的第一阶段完成

第二阶段

1.可以对属性值进行修改
2.可以调用对象方法

  • 重写初始化方法

先看一个例子

// 父类
class Person{
    var name:String
    var age:Int = 0
    var weight:Double = 0.0
    var height:Double = 0.0
    init(name:String,height:Double) {
        self.name = name
        self.height = height
    }
    init(name:String) {
        self.name = name
    }
    convenience init(name:String,age:Int,weight:Double){
        self.init(name:name)
        self.age = age
        self.weight = weight
    }
}
 // 子类
  class Man: Person {
var address:String = ""

   // 重写父类指定初始化方法
    override init(name:String) {
        super.init(name: name)
    }
    // 重写父类convenience 修饰的初始化方法 不需要添加override 关键字
     init(name:String,age:Int,weight:Double){
        super.init(name: name)
    }
    // 创建自己的初始化方法
    convenience      init(name:String,age:Int,weight:Double,address:String){
        self.init(name: name)
        self.address = address
        self.age = age
        self.weight = weight
    }  
}

总结:

1.创建新的指定初始化方法,必须调用父类的指定初始化方法 (Designated)
2.创建新的方便初始化方法,必须调用自己的指定初始化方法,或者方便初始化方法(convenience)
3.重写父类的指定初始化方法,在方法名前加override ,然后调用父类的指定初始化方法
4.重写父类的方便初始化方法(convenience) 不需要加override 或者convenience 关键字,调用父类的指定初始化方法,如果加上convenice关键字,则必须调用自己的初始化方法
5.如果子类没有初始化方法,系统会自动继承父类的初始化方法
6.初始化调用父类初始化时,需要先初始化子类的存储属性,但是如果是convenience修饰的初始化方法,要先调用自己的其他初始化方法,然后再给自己的存储属性赋值

  • 创建一个可能失败的初始化方法

注意:

1.不能在重写的初始化方法改为可能失败的初始化方法
2.不能使用相同的参数定义一个可能失败的初始化方法和不会失败的初始化方法
3.可能失败的类型可以重写为不会失败类型
4.init? 可以被重写为init!,当然可逆也是可以的
5.init?和init! 都可以被重写为init

例子1

class Man: Person {
    var address:String = ""
    convenience  init?(name:String,age:Int,weight:Double,address:String){
    if name == "" {
        return nil
    }
    self.init(name: name)
    self.address = address
    self.age = age
    self.weight = weight
    }
}

例子2

enum TemperatureUnit {
    case kelvin, celsius, fahrenheit
    init?(symbol: Character) {
        switch symbol {
       case "K":
            self = .kelvin
        case "C":
            self = .celsius
        case "F":
            self = .fahrenheit
        default:
            return nil
        }
    }
}

例子2: 子类将父类可能失败的初始化方法,修改为不会失败的类型

class Animal{
    var name:String
    init?(name:String) {
        if name.isEmpty {
            return nil
        }
        self.name = name
    }
}

对于可能出现空值的对象或者其他类型,在使用之前必须进行验证

enum TemperatureUnit: Character {
case kelvin = "K", celsius = "C", fahrenheit = "F"
}

let fahrenheitUnit = TemperatureUnit(rawValue: "F")
if fahrenheitUnit != nil {
    print("This is a defined temperature unit, so initialization     succeeded.")
}

需求: 创建一个文件类,文件名字可以为nil,但是不能为空即""

写法一:

class Document {
    var name:String?
    init?(name:String?){
        if name != nil && name!.isEmpty{
            return nil
        }
        self.name = name
    }
}

分析这种写法

只有一种初始化方法,也就是说,不管有没有名字,我们都需要给初始化传个参数,显然这样不合理,目标不明确

写法二:

class Document {
var name: String?
init() {} // 专门初始化name为 nil的情况 
init?(name: String) { // 传入名字 ,肯定不为nil ,只需要判断是否为空即可
    if name.isEmpty { return nil }
    self.name = name
}
}

疑问: init! 和init? 被重写为init 的意义何在?

暂时没想到

  • 需要的初始化方法(required)
    注意

1.子类必须重写父类用required修饰的方法
2.可以和convenience 组合使用

a-1.父类要求一个初始化方法被重写

class Person{
    var name:String
    var age:Int = 0
    var weight:Double = 0.0
    var height:Double = 0.0
    init(name:String,height:Double) {
        self.name = name
        self.height = height
    }
    init(name:String) {
        self.name = name
    }
   // 要求子类必须重写这个方法
   required convenience init(name:String,age:Int,weight:Double){
        self.init(name:name)
        self.age = age
        self.weight = weight
    }
}

a-2.子类重写父类要求的初始化方法

class Man: Person {
    var address:String = ""
    // 重写父类要求的初始化convenience 修饰的初始化方法 不需要添加override 关键字
    required init(name:String,age:Int,weight:Double){
    super.init(name: name)
   }
}
  • 反初始化(deinit)

注意:

1.deinit 在对象被释放前调用

写法很简单

deinit {
}

苹果文档有个例子简单讲解了一下它的重要性
例子: 有一个赌徒在银行存了10_000 元,赌徒从银行取钱然后去赌博,当赌徒对象释放了就将钱全部存到银行

class Bank {
    static var coinsInBank = 10_000
    static func distribute(coins numberOfCoinsRequested: Int) -> Int {
        let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
        coinsInBank -= numberOfCoinsToVend
        return numberOfCoinsToVend
    }
    static func receive(coins: Int) {
        coinsInBank += coins
    }
}

赌徒类

class Player {
    var coinsInPurse: Int
    init(coins: Int) {
        coinsInPurse = Bank.distribute(coins: coins)
  }
   func win(coins: Int) {
        coinsInPurse += Bank.distribute(coins: coins)
   }
  deinit {
        Bank.receive(coins: coinsInPurse)
    }
}

执行

var playerOne: Player? = Player(coins: 100)
playerOne!.win(coins: 2_000)
playerOne = nil
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容

  • 官方文档 初始化 Initialization是为准备使用类,结构体或者枚举实例的一个过程。这个过程涉及了在实例里...
    hrscy阅读 1,109评论 0 1
  • 初始化 (Initialization) 自从苹果2014年发布Swift,到现在已经两年多了,而Swift也来到...
    Lebron_James阅读 1,163评论 0 0
  • 初始化(Initialization) 初始化是类、结构体、枚举类型的准备过程。这个过程涉及到所有存储属性的初始化...
    泗哥阅读 5,541评论 0 3
  • #幸福是需要修出来的~每天进步1%~幸福实修08班~04-姜群-富阳# 20170629(11/99) 【幸福三朵...
    呼哈二姐阅读 197评论 1 1
  • 今天用两句赵孟頫《松雪斋书论》中的话来作个引子——学书有二:一曰笔法,二曰字形。笔法弗精,虽善犹恶;字形弗妙,虽熟...
    一只笨蛋阅读 825评论 4 6