一. 泛型的使用
func swapValue(_ a: inout Int, _ b: inout Int) {
(a, b) = (b, a)
}
var a = 1
var b = 2
swapValue(&a, &b)
print("\(a), \(b)") //2, 1
//使用泛型<T>
func swapAllValue<T>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}
var aa = "10"
var bb = "20"
swapAllValue(&aa, &bb)
print("\(aa), \(bb)") //20, 10
//继承
class Swapclass<T> {
}
class SubClass<T> : Swapclass<T> {
}
二. 泛型的原理
2.1 看SIL
可以看到调用swapAllValue是这样调用的:
- swapAllValue<string>("6666666","77777777")
- swapAllValue<Int>(10, 11)
//使用泛型<T>
func swapAllValue<T>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}
var a = 10
var b = 11
swapAllValue(&a, &b)
var aa = "66666666666666666"
var bb = "77777777777777777"
swapAllValue(&aa, &bb)
//swapAllValue 函数, 也就是`s4main12swapAllValueyyxz_xztlF`
// swapAllValue<A>(_:_:)
sil hidden @$s4main12swapAllValueyyxz_xztlF : $@convention(thin) <T> (@inout T, @inout T) -> () {
} // end sil function '$s4main12swapAllValueyyxz_xztlF'
//Int值交换 -> apply %14<Int>(%12, %13)
// function_ref swapAllValue<A>(_:_:)
%14 = function_ref @$s4main12swapAllValueyyxz_xztlF : $@convention(thin) <τ_0_0> (@inout τ_0_0, @inout τ_0_0) -> () // user: %15
%15 = apply %14<Int>(%12, %13) : $@convention(thin) <τ_0_0> (@inout τ_0_0, @inout τ_0_0) -> ()
//string值交换 -> apply %38<String>(%36, %37)
// function_ref swapAllValue<A>(_:_:)
%38 = function_ref @$s4main12swapAllValueyyxz_xztlF : $@convention(thin) <τ_0_0> (@inout τ_0_0, @inout τ_0_0) -> () // user: %39
%39 = apply %38<String>(%36, %37) : $@convention(thin) <τ_0_0> (@inout τ_0_0, @inout τ_0_0) -> ()
2.2 看汇编
- 可以看到调用的是同一个函数
// swapAllValue(&a, &b) bl 0x102904418
// swapAllValue(&aa, &bb) bl 0x102904418
2.3 总结
- 泛型用的都是一个函数,但是会将推断的类型传进去
三. associatedtype
- 作用: 给协议中用到的类型定义一个占位名称
- 协议使用泛型就要用关联类型, 类则是直接使用<T>
- 协议中可以拥有多个关联类型
protocol Stackable {
associatedtype Element //关联类型
mutating func push(_ element: Element)//mutating是为了Struct也能使用
func size() -> Int
}
class demoClass : Stackable {
typealias Element = String//声明Element是String类型,可以省略
func push(_ element: String) {
}
func size() -> Int {
return 100
}
}
四.类型约束
//类可以有类型约束 -> 泛型必须继承自demoClass
class yueshuclass<T : demoClass> {
}
//协议也可以有类型约束 -> Element需要继承自demoClass
protocol StackablePro {
associatedtype Element : demoClass
mutating func push(_ element: Element)
func size() -> Int
}
// 函数的类型约束
func equal<S1: Stackable, S2: Stackable>(_ s1: S1, _ s2: S2) -> Bool where S1.Element == S2.Element, S1.Element : Hashable {
return false
}
五. 不透明类型 (OpaqueType)
- some 用来解决协议里面有关联类型报错问题
protocol Stackable {
associatedtype Element //关联类型
mutating func push(_ element: Element)//mutating是为了Struct也能使用
func size() -> Int
}
class demoClass : Stackable {
typealias Element = String//声明Element是String类型,可以省略
func push(_ element: String) {
}
func size() -> Int {
return 100
}
}
func opaqueType(_ type: Int) -> some Stackable {
return demoClass()
}
// any是干嘛的...不知道...
func opaqueType1(_ type: Int) -> any Stackable {
return demoClass()
}
网友评论