一、前言
上篇《关键字 designated、convenience、required》中,我们了解到了 swift 在构造器这块给我们带来的新特性,结合我们之前的一篇《浅析结构体(struct)与类(class) 》,我们今天就来聊聊在 struct 与 class 中的应用与不同。
二、默认构造器
先来个灵魂拷问:何谓『默认构造器』?
不显式定义给出构造器(构造函数),由系统自动添加生成!(在 Swift 中,默认构造器就是 designated 构造器)
是不是光看文字理解有点困难?那我就来个 demo 演示。
2.1、struct
struct DemoStruct {
var name: String
var age: Int
}
没有构造方法(init),但我们可以这么来初始化使用:
struct-before.png当我们输入『左括号』时,Xcode 自动提示,给了我们一个唯一的初始化方法,这个就是『默认构造器』,我们也可以显式这样来创建:
struct-init.png即通过 init 构造器来初始化,但同样,Xcode 也提示我们有两个参数。为啥是有参数,而不是无参,例如:DemoStruct.init() ?
2.1.1、逐一成员构造器
这是 Swift 规范:当我们没有显式指定至少一个 init 构造器时,swift 会为我们添加一个默认构造器,该构造器的入参即是 struct 中的所有成员!
上面例子中,我们定义了两个成员,分别是:name 和 age,因此,swift 会按照从上到下,依次将其纳入到默认构造器中,即创建了如下构造器:
swift-struct.png如果 struct 讲到这里就完了,是不是很没意思?如果你认为这就完了,你就『Too Young Too Simple』了!
如果我们的 struct 中有很多成员变量,虽然 swift 会为我们创建默认构造器,但是,我们在使用时,每个参数都需要传入,使用就会很麻烦,那有没有其它方式呢?例如,初始化时,我只想传 name :
optional.png上面的代码片段没有报错,运行无任何问题!
我们有三种解决方式:
- 可选参数默认构造器;
- 默认参数默认构造器;
- 扩展构造器;
2.1.2、可选参数默认构造器
param-nil.png我们看到,age 的类型是 Int? ,但可为 nil;因此,我们可以在初始化时,只需要传入强制必要的参数:
struct-param-nil.png2.1.3、默认参数默认构造器
名字有点绕,但效果很简单:
param-def.png2.1.4、扩展构造器
扩展,即 extension ,swift 提供的一种方式,无论是 struct 还是 class 都可以使用:
// 扩展 struct
extension DemoStruct {
// 重载一个构造器
// 该构造器调用默认构造器
init(name: String) {
self.init(name: name, age: 18)
}
}
执行结果如下:
struct-result.png2.2、class
同样,先来定义一个 class,代码如下:
class DemoClass {
var name: String
var age: Int
}
如果仅是这样,Xcode 会立即提示报错(类没有构造器):
no-init.png我们至少需要显式指定(explicit designated)一个构造器,对于 DemoClass,我们要按照类似 struct 的逐一成员构造器那样,定义一个构造器,如果只构造部分成员的构造器,则会如下报错:
not-all-init.png该错误提示:没有初始化所有的成员。对于这种情况,我们有三种方式来完成:
- 将 age 设置为可默认为 nil 类型(等同于 2.1.2);
- 定义 age 时就给定默认值(等同于 2.1.3);
- 在构造器中给定默认值(如下代码所示);
class DemoClass {
var name: String
var age: Int
init(name: String) {
self.name = name
// 构造器中给定默认值
self.age = -1
}
}
class 要求必需显式指定一个构造器,而 struct 则是由 swift 自动添加。同样,class 也可以通过扩展(extension)来重载构造器(注:扩展类的构造器,是需要便利的,即添加关键字:convenience):
extension DemoClass {
convenience init(name: String, age: Int) {
self.init(name: name)
self.age = age
}
}
我们执行看下结果:
class-result.png三、可失败构造器
类似 Kotlin 都有一种类型叫可null类型,Swift 也不甘落后,也有可空类型,而且 Swift 更进一步,允许在创建变量(struct)、对象(class)或枚举时,返回空对象(即创建失败,返回为 nil )。
- 什么叫空类型?
// T 代表任何类型
// variable 代表变量、对象
var variable: T? = nill
// 例如:
var str: String? = nil // 可 nil 字符串
var num: Int? = nil // 可 nil 整型
- 如何定义可失败构造器?
可失败构造器定义非常简单,只需要在 init 后加个问号,即:init? 即可,例如下图:
define-init-nil.png我们可以看到,我们定义了一个可失败构造器,如果创建 Person 时,传入的字符串是『空字符串』,那么我们就返回 nil,否则就成功创建。从上图中,我们还能发现,可失败构造器的返回类型是:T?,在上面的例子中,返回类型是 Person?,即代表可能为 nil 。
dif-use-init-nil.png上图是我们的测试代码,执行后打印结果非常清楚。对于 class 或者 enum ,与 struct 类似,我就不再演示,大家可自行测试。
四、个人感想
可人有些朋友要问:为何要花如此大的力气来分析 struct 和 class ?难道就是因为 Swift 新增了 struct 所以才写这些么?
不,因为我在做《iOS Swift5从0到1系列》中,发现每当我实现一些功能时,就会或多或少涉及到一些 Swift 的新特性,虽然这些特性在 Swift 一出来就有,但是,我不确定大家都非常的了解熟悉,因此,但凡涉及到 Swift 中新的知识点,我都会单独开一些分支系列来提前讲解分析,希望大家能够一点一点的学习与吸收,而不是我一下子抛出很多新的知识点,导致大家难以消化吸收,影响心情放中途放弃。
Swift 其实非常简单,我希望让大家和我一起共同成长进步,还可以快乐的交流,并且,本着我的博客中,所有的文章都是高质量,且可吸收(无论是 iOS 还是 Java、Android 或者 H5),因此,我会在讲解主线的同时,穿插不同支线;同时,一篇高质量的博文也要好几天(哪怕是分支内容),因此,希望大家不要心急。
谢谢!
网友评论