泛型可以将类型参数化,提高代码复用率,减少代码量。
注意:
C++ 是通过实现多个不同类型的方法来实现泛型
Swift 是通过传入泛型的元类型来实现泛型
- 交换两个Int类型的值
func swapValues(_ v1: inout Int, _ v2: inout Int) {
let temp = v1
v1 = v2
v2 = temp
}
var n1 = 10
var n2 = 20
swapValues(&n1, &n2)
print(n1, n2) // 20 10
- 交换两个入参的值(可能是Int,Double,String),这个时候就要用到泛型
func swapValues2<T>(_ v1: inout T, _ v2: inout T) {
(v1,v2) = (v2,v1)
}
var a = 10
var b = 20
swapValues2(&a, &b)
print(a, b)//20 10
a = "ABC"
b = "abc"
swapValues2(&a, &b)
print(a, b)//abc ABC
对于C++来说,会分别生成
func swapValues2(_ v1: inout Int, _ v2: inout Int)
以及func swapValues2(_ v1: inout String, _ v2: inout String)
两个函数对于Swift来说,
在传入参数时,会把该参数的元类型(type metadata
)一起传入
- 泛型函数赋值给变量
func test<T1, T2>(_ v1: T1, _ v2 : T2) -> [Any] {
return [v1,v2]
}
var fn : (Int, Double) ->([Any]) = test
print(fn(10,20.0))
- 泛型类
class Stack<T> {
var elements = [T]()
func push(element: T) {
elements.append(element)
}
func pop() {
elements.removeLast()
}
func top() -> T {
elements.last!
}
}
var stac = Stack<Int>()
stac.push(element: 5)
stac.push(element: 6)
stac.pop()
print(stac.elements)
print(stac.top())
/*
[5, 6]
6
*/
- 泛型类的继承
class subStack<T>: Stack<T> {
}
- 关联类型(协议中实现泛型)
- 关联类型的作用:给协议中用到的类型定义一个占位名称
- 协议中可以拥有多个关联类型
protocol Stackable {
associatedtype Element// 关联类型
mutating func push(_ element: Element)
mutating func pop() -> Element
func top() -> Element
func size() -> Int
}
class StringStack: Stackable {
typealias Element = String//给关联类型设定真实类型 可省略
var elements = [String]()
func push(_ element: String) {
elements.append(element)
}
func pop() -> String {
elements.removeLast()
}
func top() -> String {
elements.last!
}
func size() -> Int {
elements.count
}
}
class IntStack<E> :Stackable{
typealias E = Int //给关联类型设定真实类型 可省略
var elements = [Int]()
func push(_ element: Int) {
elements.append(element)
}
func pop() -> Int {
elements.removeLast()
}
func top() -> Int {
elements.last!
}
func size() -> Int {
elements.count
}
}
- 类型约束
protocol Runnable{
}
func lxys(){
class Person{}
func swapValues<T: Person&Runnable>(_ a: inout T, _ b: inout T ){
(a, b) = (b,a)
}
}
【泛型使用注意点】
示例1: 协议中有associatedtype
解决方案1:强制转换时可能会出错。
protocol Runnable {
associatedtype Speed
var speed : Speed{get}
}
class Person: Runnable {
var speed: Double {
10.0
}
}
class Car: Runnable {
var speed: Int {
20
}
}
//func get(_ type: Int) -> Runnable {
// if type == 0 {
// return Person()
// }
// return Car()
//}
func get<T: Runnable>(_ type: Int) -> T {
if type == 0 {
return Person() as! T
}
return Car() as! T
}
解决方案2: 不透明类型 some
- 使用some关键字声明一个不透明类型
- some限制只能返回一种类型
- some一般可以用在返回值类型上,也可以用在属性类型上面
// 解决方案2
func get(index: Int) -> some Runnable {
return Car()
}
class Person{
var per: some Runable{
return Dog()
}
}
网友评论