本篇主要讲解 Swift 中 Designated、Convenience和 Required 的使用:

  在 OC 中 init 方法是非常不安全的,没人能够保证 init 只被调用一次,也没有人保证在初始化方法调用以后实例的各个变量都完成初始化,甚至如果在初始化里使用属性进行设置的的话,还可能会造成各种问题。Swift 强化了 designated 初始化方法的地位。swift 中不加修饰的 init 方法都需要在方法中保证所有非 Optional 得实例变量被赋值初始化,而在子类中也强制(显示或隐式的)调用 super 版本的 designated 初始化,所以无论怎样被初始化的对象总是可以完成完整的初始化的。

class ClassA {
let numA: Int
init(num: Int) { // 不加修饰的 init 方法都需要在方法中保证所有非 Optional 得实例变量被赋值初始化
numA = num
}
} class ClassB: ClassA {
let numB: Int
override init(num: Int) {
numB = num + // 在 init 里我们可以对 let 的实例常量进行赋值,这是初始化方法的重要特点。正常情况下 let 声明的值是不可变的,无法被赋值,这对构建线程安全的 API 十分有用。而 init 只可能被调用一次,所以在 init 里我们可以为不变量进行赋值,而不会引起任何线程安全的问题
super.init(num: num)
}
}

  与 designated 初始化方法啊对应的是在 init 前加上 convenience 关键字的初始化方法。这类方法只作为补充和提供使用上的方便。所有的 convenience 初始化方法都必须调用同一个类中的 designated 初始化完成设置,另外 convenience 的初始化方法是不能被子类重写或者是从子类中以 super 的方式被调用的。

class ClassAA {
let numA: Int
init(num: Int) {
numA = num
}
convenience init(bigNum: Bool) {
self.init(num: bigNum ? : ) // 所有的 convenience 初始化方法都必须调用同一个类中的 designated 初始化完成设置
}
} class ClassBB: ClassAA {
let numB: Int
override init(num: Int) {
numB = num +
super.init(num: num)
}
}

  只要在子类中实现重写了父类 convenience 方法所需要的 init 方法的话,我们在子类中就可以使用父类的 convenience 初始化方法了。比如上面我们及时在 ClassBB 中没有 bigNum 版本的 convenience init(bigNum: Bool),我们仍然是可以是用这个方法来完成子类初始化的:

let anObj = ClassBB(bigNum: true)
print(anObj.numA, anObj.numB)

输出结果:

总结:初始化方法永远遵循以下两个原则

1.初始化路径必须保证对象完全初始化,这可以通过调用本类型的 designated 初始化方法得到保证;

2.子类的 designated 初始化方法必须调用父类的 designated 方法,以保证父类也完成初始化。

  对于某些我们希望子类中一定实现的 designated 初始化方法,我们可以通过添加 required 关键字进行限制,强制子类对这个方法重写实现。这样做的最大的好处是可以保证依赖于某个 designated 初始化方法的 convenience 一直可以被使用。

下面的代码中如果希望初始化方法对于子类一定可用,就将 init(num: Int) 声明为必须。

class ClassAAA {
let numA: Int
required init(num: Int) {
numA = num
}
required convenience init(bigNum: Bool) {
self.init(num: bigNum ? : )
} }
class ClassBBB: ClassAAA {
let numB: Int
required init(num: Int) {
numB = num +
super.init(num: num)
}
}
let sencondObj = ClassBB(bigNum: true)
print(sencondObj.numA, sencondObj.numB)

输出结果:

对于 convenience 的初始化方法我们也可以加上 required 以确保子类对其进行实现。

最新文章

  1. OpenWebGlobe-开源三维GIS初体验(附源码和演示)
  2. XML通过XSL格式化的那点事(XML到自定义节点折叠显示)
  3. Node.js入门笔记(3):全局对象(2)
  4. opencv初体验
  5. ZOJ 刷题记录 小黑屋 (`・д・´)
  6. IoC容器Autofac正篇之类型关联(服务暴露)(七)
  7. Linux下vim文件未正常退出,修复文件
  8. api接口对于客户端的身份认证方式以及安全措施
  9. Ionic的项目结构-工程目录
  10. Entity Framework 学习中级篇2—存储过程(上)
  11. javascript DOM(2) 一个网页上切换显示不同的图片或文本
  12. 突然兴起复习一下Swift3.0
  13. 如何在不同的语言/平台中获取Android ID
  14. html学习第二弹の表格的使用方法
  15. 【Dojo 1.x】笔记5 使用本地引用
  16. JavaScript 笔记(二) 正则表达式
  17. Visual Studio Code 配置 gcc
  18. git merge和git rebase的区别(转)
  19. Python的zip函数(转)
  20. Appium的Java封装

热门文章

  1. 二、Sink例程
  2. Dapper学习 - Dapper的基本用法(二) - 存储过程/函数
  3. WinPhone学习笔记(一)——页面导航与页面相关
  4. Mssql中一些常用数据类型的说明和区别
  5. Java总结篇系列:类型转换/造型
  6. .net批量上傳Csv檔資料應用程序開發總結
  7. scala泛函编程是怎样被选中的
  8. ubuntu 下安装redis 以及php扩展
  9. Web Serveice服务代理类生成及编译
  10. 高效 Java Web 开发框架 JessMA v3.2.3 正式发布