Swift进阶黄金之路(一)

本文深入探讨了Swift中的高级特性,包括协议如ExpressibleByDictionaryLiteral、Sequence、Collection等,关键字如public、static、infix operator等,以及高阶函数如Filter、Map和Reduce。此外,还介绍了Swift中的柯里化、面向协议编程与面向对象编程的区别,以及错误处理中的try、throw、catch概念。通过本文,读者可以深化对Swift语言的理解,提高编程技能。

Swift进阶黄金之路(二)

这篇是对一文鉴定是Swift的王者,还是青铜文章中问题的解答。这些问题仅仅是表层概念,属于知识点,在我看来即使都很清楚也并不能代表上了王者,如果非要用段位类比的话,黄金还是合理的😄。

Swift是一门上手容易,但是精通较难的语言。即使下面这些内容都不清楚也不妨碍你开发业务需求,但是了解之后它能够帮助我们写出更加Swifty的代码。

一、 协议 Protocol

ExpressibleByDictionaryLiteral

ExpressibleByDictionaryLiteral是字典的字面量协议,该协议的完整写法为:

public protocol ExpressibleByDictionaryLiteral {
    /// The key type of a dictionary literal.
    associatedtype Key
    /// The value type of a dictionary literal.
    associatedtype Value
    /// Creates an instance initialized with the given key-value pairs.
    init(dictionaryLiteral elements: (Self.Key, Self.Value)...)
}
复制代码

首先字面量(Literal)的意思是:用于表达源代码中一个固定值的表示法(notation)

举个例子,构造字典我们可以通过以下两种方式进行:

// 方法一:
var countryCodes = Dictionary<String, Any>()
countryCodes["BR"] = "Brazil"
countryCodes["GH"] = "Ghana"
// 方法二:
let countryCodes = ["BR": "Brazil", "GH": "Ghana"]
复制代码

第二种构造方式就是通过字面量方式进行构造的。

其实基础类型基本都是通过字面量进行构造的:

let num: Int = 10
let flag: Bool = true
let str: String = "Brazil"
let array: [String] = ["Brazil", "Ghana"]
复制代码

而这些都有对应的字面量协议:

ExpressibleByNilLiteral // nil字面量协议
ExpressibleByIntegerLiteral // 整数字面量协议
ExpressibleByFloatLiteral // 浮点数字面量协议
ExpressibleByBooleanLiteral // 布尔值字面量协议
ExpressibleByStringLiteral // 字符串字面量协议
ExpressibleByArrayLiteral // 数组字面量协议
复制代码

Sequence

Sequence翻译过来就是序列,该协议的目的是一系列相同类型的值的集合,并且提供对这些值的迭代能力,这里的迭代可以理解为遍历,也即for-in的能力。可以看下该协议的定义:

protocol Sequence {
    associatedtype Iterator: IteratorProtocol
    func makeIterator() -> Iterator
}
复制代码

Sequence又引入了另一个协议IteratorProtocol,该协议就是为了提供序列的迭代能力。

public protocol IteratorProtocol {
    associatedtype Element
    public mutating func next() -> Self.Element?
}
复制代码

我们通常用for-in实现数组的迭代:

let animals = ["Antelope", "Butterfly", "Camel", "Dolphin"]
for animal in animals {
    print(animal)
}
复制代码

这里的for-in会被编译器翻译成:

var animalIterator = animals.makeIterator()
while let animal = animalIterator.next() {
    print(animal)
}
复制代码

Collection

Collection译为集合,其继承于Sequence。

public protocol Collection : Sequence {
  associatedtype Index : Comparable
  var startIndex: Index { get }
  var endIndex: Index { get }
  var isEmpty: Bool { get }
  var count: Int { get }
  
  subscript(position: Index) -> Element { get }
  subscript(bounds: Range<Index>) -> SubSequence { get }
}
复制代码

是一个元素可以反复遍历并且可以通过索引的下标访问的有限集合,注意Sequence可以是无限的,Collection必须是有限的。

CollectionSequence的基础上扩展了下标访问、元素个数能特性。我们常用的集合类型ArrayDictionarySet都遵循该协议。

CustomStringConvertible

这个协议表示自定义类型输出的样式。先来看下它的定义:

public protocol CustomStringConvertible {
    var description: String { get }
}
复制代码

只有一个description的属性。它的使用很简单:

struct Point: CustomStringConvertible {
    let x: Int, y: Int
    var description: String {
        return "(\(x), \(y))"
    }
}

let p = Point(x: 21, y: 30)
print(p) // (21, 30)
//String(describing: <#T##CustomStringConvertible#>)
let s = String(describing: p)
print(s) // (21, 30)
复制代码

如果不实现CustomStringConvertible,直接打印对象,系统会根据默认设置进行输出。我们可以通过CustomStringConvertible对这一输出行为进行设置,还有一个协议是CustomDebugStringConvertible

public protocol CustomDebugStringConvertible {
    var debugDescription: String { get }
}
复制代码

CustomStringConvertible用法一样,对应debugPrint的输出。

Hashable

我们常用的DictionarySet均实现了Hashable协议。Hash的目的是为了将查找集合某一元素的时间复杂度降低到O(1),为了实现这一目的需要将集合元素与存储地址之间建议一种尽可能一一对应的关系。

我们再看Hashable`协议的定义:

public protocol Hashable : Equatable {
    var hashValue: Int { get }
    func hash(into hasher: inout Hasher)
}

public protocol Equatable {
    static func == (lhs: Self, rhs: Self) -> Bool
}
复制代码

注意到func hash(into hasher: inout Hasher),Swift 4.2 通过引入 Hasher 类型并采用新的通用哈希函数进一步优化 Hashable

如果你要自定义类型实现 Hashable</

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值