HR's Blog

Swimming 🏊 in the sea🌊of code!

0%

Swift关键字Some:浑浊类型(Opaque return types)到清晰(Opaque types)的类型的转变

.

最近开始使用SwiftUI进行编程,我们总能看到body后面有个关键字some来修饰,那这个some到底是什么意思?

1
2
3
4
5
6
7
8
9
10
11
12
import SwiftUI

struct ContentView: View {
var body: some View {
Text("Hello, world!") .padding()
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View { ContentView()
}
}

问题

主要介绍Swift新引入的浑浊类型和清晰类型,以及加入关键字some以后,将浑浊类型变成清晰类型。

1
2
3
4
5
6
7
8
9
10
func makeNumber() -> Equatable {
return 5
}

let intA = makeNumber()
let intB = makeNumber()

if intA == intB { //❌Protocol 'Equatable' can only be used as a generic constraint because it has Self or associated type requirements
print("equal")
}

在上面的代码中,返回的Equatable是一个约束条件的浑浊类型,所以并不能在后面用==判断是否相等。因为Equatable这个协议,有可能stirng类型和int类型都遵守了,你也可以返回stirng或者是int,string和int并不能彼此比较。所以编译器并不能只通过这个Equatable协议就把它当作一个类型来使用,对于编译器来说里面返回的类型,其实是浑浊的,有可能是遵守了Equatabl不同的类型。

通过范型解决

1
2
3
func makeNumber<T: Equatable>() -> T {
return 5 as! T
}

我们可以在这个方法的一开始就传入关联的范型类型,这样在编译器在变异期间就能看出返回的具体类型,编译器也就不会在报错了。

Swift5.1新特性 some 关键字

通过范型来解决的问题的思路还是不够完善,因为在很多情况下,返回的类型我们是可以确定的。我们就可以使用Swift 5.1的在协议前面加上some来将函数返回的浑浊类型(Opaque return types)变成清晰(Opaque types)的类型, 这样也就可以在不需要将函数改为范型来解决问题。

1
2
3
func someFunction() -> some Equatable {
return 1
}

加上some这种浑浊转清晰的前提是编译器能推断出来,你即将返回的类型。如果你函数返回的Int和String随机返回的话,编译器还是会报错。

1
2
3
4
5
6
7
func buySomething() -> some Equatable {  //❌Function declares an opaque return type, but the return statements in its body do not have matching underlying types
if Int.random(in: 1...2) == 1 {
return 1
} else {
return "1"
}
}

References

Swift 5.1 新特性:透明类型关键字 some