本篇主要讲解 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 以确保子类对其进行实现。

Swift开发第十一篇——Designated、Convenience和Required的更多相关文章

  1. Swift开发第十篇——可变参数函数&初始化方法顺序

    本篇分为两部分: 一.Swift中的可变参数函数 二.初始化方法的顺序 一.Swift中的可变参数函数 可变参数函数指的是可以接受任意多个参数的函数,在 OC 中,拼接字符串的函数就属于可变参数函数 ...

  2. Swift开发第八篇——方法嵌套&命名空间

    本篇分为两部分: 一.Swift中的方法嵌套 二.Swift中的命名空间 一.Swift中的方法嵌套 在 swift 中我们可以让方法嵌套方法,如: func appendQuery(var url: ...

  3. Swift开发第七篇——字面量转换&下标

    本篇分为两部分: 一.Swift 中的字面量转换 二.Swift 中的下标 一.Swift 中的字面量转换 所谓字面量就是指像特定的数字,字符串或者是布尔值这样能够直接了当地指出自己的类型并未变量进行 ...

  4. Swift开发第六篇——操作运算符也可以重载& func 的参数修饰

    本篇分为两部分: 1.Swift 中重载操作运算符的使用 2.Swfit 中 func 的参数修饰 1.Swift 中重载操作运算符的使用 与别的语言不同,Swift 支持运算符的重载,运算符指的是“ ...

  5. Swift开发第五篇——四个知识点(Struct Mutable方法&Tuple&autoclosure&Optional Chain)

    本篇分三部分: 一.Struct Mutable方法 二.多元组(Tuple) 的使用 三.autoclosure 的使用 四.Optional Chain 的使用 一.Struct Mutable方 ...

  6. Swift开发第四篇——柯里化

    本篇分为两部分: 一.柯里化的基本使用 二.柯里化的使用场景 一.柯里化的基本使用 柯里化(Currying):也就是把接受多个参数的方法变换成接受第一个参数的方法,并且返回接受余下的参数并且返回结果 ...

  7. Swift开发第三篇——Playground

    本篇分为两部分: 一.Playground的延时运行 二.Playground的可视化 一.Playground的延时运行 Playground 就是提供一个可以即时编译的类似 REPL 的环境,他为 ...

  8. PowerBI开发 第十一篇:报表设计技巧(更新)

    PowerBI版本在持续的更新,这使得报表设计能够实现更多新的功能,您可以访问 PowerBI Blog查看PowerBI的最新更新信息,本文总结了PowerBI新版本的重要更新和设计技巧. 我的Po ...

  9. swift开发多线程篇 - 多线程基础

    swift开发多线程篇 - 多线程基础 iOS 的三种多线程技术 (1)NSThread  使用NSThread对象建立一个线程非常方便 但是!要使用NSThread管理多个线程非常困难,不推荐使用 ...

随机推荐

  1. 如何在自己的窗体(控件)中显示XAF的视图

    Form form = new Form(); DevExpress.ExpressApp.View listView = Application.CreateListView(Application ...

  2. Spring Framework------>version4.3.5----->Reference学习心得----->总结

    1.Spring Framework概述: 有很多可用版本,网址http://projects.spring.io/spring-framework/       2.Spring Framework ...

  3. odoo报表条码无法显示解决[转]

    当服务器为Linux(Ubuntu)时,ODOO打印的报表上是有条码的,却显示空白框框.问题在于服务器上没有安装条码的字体,reportlab渲染条码图形失败,导致显示不正常. 将附件中的字体下载,解 ...

  4. SQL SERVER2012中使用游标来备份数据库

    在SQL SERVER中,添加JOB,可以使用以下语句设置定期备份数据库. DECLARE @name VARCHAR(50)--databasename DECLARE @path VARCHAR( ...

  5. 学习Shell脚本编程(第4期)_在Shell程序中的使用变量

    变量的赋值 变量的访问 变量的输入 4.1 变量的赋值     在Shell编程中,所有的变量名都由字符串组成,并且不需要对变量进行声明.要赋值给一个变量,其格式如下: 变量名=值  注意: 等号(= ...

  6. CSS高级技巧

    使用CSS复位 CSS复位可以在不同的浏览器上保持一致的样式风格.您可以使用CSS reset 库Normalize等,也可以使用一个更简化的复位方法:· * { box-sizing: border ...

  7. MySQL的数据备份以及pymysql的使用

    一.MySQL的数据备份 语法: # mysqldump -h 服务器 -u用户名 -p密码 数据库名 > 备份文件.sql #示例: #单库备份 mysqldump -uroot -p123 ...

  8. Android + HTML5 混合开发

    摘要: 对于 Android + HTML5 混合开发以下的观点仅仅是我的个人观点,如果有什么不对的地方请指正 简介: 混合开发的 App(Android + HTML5)就是在一个 App 中内嵌一 ...

  9. 如何写对kubernetes的模板文件

    kubernetes的模板配置文件随着版本更迭也会有相应的调整,正确配置模板关键字的方式是参考版本发布的doc,如下图 在docs\api-reference下面有不同功能的API目录,如下图 各个A ...

  10. css 子盒子上下居中 文字溢出省略号

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...