答“卓同学的 Swift 面试题”--上篇

这是卓同学的 Swift 面试题 强行来答一波,如有歧义、错误、不全,欢迎指(来)正(喷)。
面试题基础篇有36题,高级篇8题,哲学篇2题。先就基础篇前11题进行回答。也为接下来的面试做些准备 🤔

1. class 和 struct 的区别
2. 不通过继承,代码复用(共享)的方式有哪些
3. Set 独有的方法有哪些?
4. 实现一个 min 函数,返回两个元素较小的元素
5. map、filter、reduce 的作用
6. map 与 flatmap 的区别
7. 什么是 copy on write
8. 如何获取当前代码的函数名和行号
9. 如何声明一个只能被类 conform 的 protocol
10. guard 使用场景
11. defer 使用场景
1. class 和 struct 的区别

此题可参见 The Swift Programming Language,有专门的一节是用来介绍class 和 struct 的。我也是从中总(搬)结(运)来的。
在 Swift 中,class 和 struct 的关系可以说是非常之亲密。
相同点: 我们可以使用完全使用相同的语法规则来为 class 和 struct 定义属性、方法、下标操作、构造器,也可以通过extension 和 protocol 来提供某种功能。
不同点:
1)与 struct 相比,class 还有如下功能:

  • 继承允许一个类继承另一个类的特性
  • 类型转换允许在运行时检查和解释一个类实例的类型
  • 析构器允许一个类实例释放任何其所被分配的资源
  • 引用计数允许对一个类的多次引用

2) Value Types & Reference Types:

  • struct 是值类型 (Value Types) 即:通过被复制的方式在代码中传递,不使用引用计数
  • class 是引用类型(Reference Types) 即:引用类型在被赋予到一个变量、常量或者被传递到一个函数时,其值不会被拷贝。因此,引用的是已存在的实例本身而不是其拷贝

3) 分配方式

4) 方法派发

更多关于值类型和引用类型的知识,请参见Value Types & Reference Types

2. 不通过继承,代码复用(共享)的方式有哪些

我们都知道代码复用的好处:可以降低开发成本、增加代码的可靠性并提高它们的一致性。
在Swift中,除了通过继承,还可以通过** * 扩展、协议* ** 来实现代码复用。

扩展 --- Extensions

扩展 就是为一个已有的类、结构体、枚举类型或者协议类型添加新功能。这包括在没有权限获取原始源代码的情况下扩展类型的能力(即 逆向建模 )。扩展和 Objective-C 中的分类类似。

Swift 中的扩展可以:

  • 添加计算型属性和计算型类型属性
  • 定义实例方法和类型方法
  • 提供新的构造器
  • 定义下标
  • 定义和使用新的嵌套类型
  • 使一个已有类型符合某个协议

更多扩展知识,请移步:Extensions

协议 --- Protocols

协议 规定了用来实现某一特定任务或者功能的方法、属性,以及其他需要的东西。类、结构体或枚举都可以遵循协议,并为协议定义的这些要求提供具体实现
另外,规定了用来实现某一特定任务或者功能的方法、属性,以及其他需要的东西。类、结构体或枚举都可以遵循协议,并为协议定义的这些要求提供具体实现

这里只是简单叙述下,更多协议知识,请移步:Protocols

3. Set 独有的方法有哪些
intersect(_:)// 根据两个集合中都包含的值创建的一个新的集合
exclusiveOr(_:) // 根据只在一个集合中但不在两个集合中的值创建一个新的集合
union(_:) // 根据两个集合的值创建一个新的集合
subtract(_:) //根据不在该集合中的值创建一个新的集合
isSubsetOf(_:) //判断一个集合中的值是否也被包含在另外一个集合中
isSupersetOf(_:) //判断一个集合中包含的值是否含有另一个集合中所有的值
isStrictSubsetOf(:) isStrictSupersetOf(:) //判断一个集合是否是另外一个集合的子集合或者父集合并且和特定集合不相等
isDisjointWith(_:) //判断两个集合是否不含有相同的值

let houseAnimals : Set = ["?","?"]
let farmAnimals: Set = ["?","?","?","?","?"]
let cityAnimals: Set = ["?","?"]
houseAnimals. isSubsetOf(farmAnimals)
//true
farmAnimals. isSupersetOf(houseAnimals)
//true
farmAnimals. isDisjointWith(cityAnimals)
//true
集合的基本操作
4.实现一个 min 函数,返回两个元素较小的元素
func min<T: Comparable>(_ a: T, _ b: T) -> T {
    return a < b ? a: b
}
//这里一定要遵守 Comparable 协议,因为并不是所有的类型都具有“可比性”
5.map、filter、reduce 的作用
  • map 是Array类的一个方法,我们可以使用它来对数组的每个元素进行转换
let intArray = [1, 3, 5]
let stringArr = intArray.map {
            return "\($0)"
        }
// ["1", "3", "5"]
  • filter 用于选择数组元素中满足某种条件的元素
let filterArr = intArray.filter {
    return $0 > 1
}
//[3, 5]
  • reduce 把数组元素组合计算为一个值
let result = intArray.reduce(0) {
    return $0 + $1
}
//9
6.map 与 flatmap 的区别
  • map 可以对一个集合类型的所有元素做一个映射操作
  • 和map 不同,flatmap 有两个定义,分别是:
func flatMap(transform: (Self.Generator.Element) throws -> T?) -> [T]
func flatMap(transform: (Self.Generator.Element) -> S) -> [S.Generator.Element]
let intArray = [1, 2, 3, 4]
result = intArray.flatMap { $0 + 2 }
// [3,4,5,6]
对数组进行flatmap操作,和map是没有区别的

1) 第一种情况返回值类型是 T?, 实际应用中,可以用来过滤元素为nil的情况,(内部使用了 if-let 来对nil值进行了过滤) 例如:

let optionalArray: [String?] = ["AA", nil, "BB", "CC"];
var optionalResult = optionalArray.flatMap{ $0 }
// ["AA", "BB", "CC"]
操作前是[String?], 操作后会变成[String]

2) 第二种情况可以进行“降维”操作

let numbersCompound = [[1,2,3],[4,5,6]];
var res = numbersCompound.map { $0.map{ $0 + 2 } }
// [[3, 4, 5], [6, 7, 8]]
var flatRes = numbersCompound.flatMap { $0.map{ $0 + 2 } }
// [3, 4, 5, 6, 7, 8]

0.map{0 + 2 } 会得到[3, 4, 5], [6, 7, 8], 然后遍历这两个数组,将遍历的元素拼接到一个新的数组内,最终并返回就得到了[3, 4, 5, 6, 7, 8]

7.什么是 copy on write

copy on write, 写时复制,简称COW,它通过浅拷贝(shallow copy)只复制引用而避免复制值;当的确需要进行写入操作时,首先进行值拷贝,在对拷贝后的值执行写入操作,这样减少了无谓的复制耗时。

应用场景 :

写时复制最擅长的是并发读取场景,即多个线程/进程可以通过对一份相同快照,去处理实效性要求不是很高但是仍然要做的业务(比如实现
FS\DB备份、日志、分析)
适用于对象空间占用大,修改次数少,而且对数据实效性要求不高的场景

参考:Copy-on-write的介绍与应用

8.如何获取当前代码的函数名和行号
  • 获取函数名: #function
  • 获取行号:#line
  • 获取文件名: #file
  • 获取列:#column
9.如何声明一个只能被类 conform 的 protocol

协议的继承列表中,通过添加 class 关键字来限制协议只能被类类型遵循,而结构体或枚举不能遵循该协议。class 关键字必须第一个出现在协议的继承列表中,在其他继承的协议之前:

protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
    // 这里是类类型专属协议的定义部分
}
10.guard 使用场景

使用 guard 来表达 “提前退出”的意图,有以下使用场景

  • 在验证入口条件时
  • 在成功路径上提前退出
  • 在可选值解包时(拍扁 if let..else 金字塔)
  • return 和 throw 中
  • 日志、崩溃和断言中
    而下面则是尽量避免使用的场景:
  • 不要用 guard :替代琐碎的 if..else 语句
  • 不要用 guard :作为 if 的相反情况
  • 不要:在 guard 的 else 语句中放入复杂代码
    具体参见 使用 guard 的正确姿势
11.defer 使用场景

defer 语句用于在退出当前作用域之前执行代码.例如:
手动管理资源时,比如 关闭文件描述符,或者即使抛出了错误也需要执行一些操作时,就可以使用 defer 语句。
如果多个 defer 语句出现在同一作用域内,那么它们执行的顺序与出现的顺序相反

func f() {
    defer { print("First") }
    defer { print("Second") }
    defer { print("Third") }
}
f()
// 打印 “Third”
// 打印 “Second”
// 打印 “First”

详细讲解请参考喵神的文章:关于 Swift defer 的正确使用

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

推荐阅读更多精彩内容