swift學習筆記->泛型


如果學過java就知道泛型是什么  比如說定義一個數組  var a : [Int] 

Int 就是該數組的泛型 創建一個字典也是根據泛型儲存內容的

var a : Dictionary <String,String>

而泛型能解決的問題  就像字典一樣  他是個不確定的鍵值對  你定義什么類型就能存什么類型

泛型函數

下面舉個例子一個函數  要將兩個參數值互換

func  myswap(inout a: Int,inout b: Int) {
    let temp  = a
    a = b
    b = temp
   }

如上所寫   只能交換int類型數據   如果要String類型呢    是不是又要另外寫一份?

這里用泛型就省力了   把參數類型改成未知的一個泛型一般用 "T"

func  myswap<T>(inout a: T,inout b: T) {
    let temp  = a
    a = b
    b = temp
}

語法就不多解釋了  尖括號寫的是泛型  形參用就可以了

這樣只要滿足運算符"="操作的類型就能交換

泛型類型

在類或結構中定義一個泛型類型    下面舉個栗子

class Stack<Element> {
    var containers = [Element]()
     func push(e: Element) {
        containers.append(e)
    }
     func pop() -> Element {
        return containers.removeLast()
    }
}

  var data: Stack<Int> = Stack<Int>()

這個類是模仿棧的結構有push入棧與pop出棧兩個方法

類中的數組在類實例化時決定

泛型擴展

擴展時,不需要再指定泛型參數(尖括號里面的內容稱之為泛型參數)

extension Stack {
    var count: Int {
        return containers.count
    }
  
  func aa(e:Element){
    print(e)
  }
} 
var data2
= Stack<String>()
data2.push(
"dasdf")
data2.count

 

泛型約束

你可以寫一個在一個類型參數名后面的類型約束,通過冒號分割,來作為類型參數鏈的一部分。這種作用於泛型函數的類型約束的基礎語法如下所示(和泛型類型的語法相同):

func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
    // function body goes here
}

 

上面這個假定函數有兩個類型參數。第一個類型參數T,有一個需要T必須是SomeClass子類的類型約束;第二個類型參數U,有一個需要U必須遵循SomeProtocol協議的類型約束。

用處也跟泛型函數類似  比如寫一個查找數組中是否有該數  有則返回下標  沒有則返回-1

func index<T:Equatable>(arr:[T],data: T) ->Int {
    for (m,n) in arr.enumerate() {
        if n == data  {
            return m
        }
    }
    return -1
}

這樣寫也就意味着“任何T類型都遵循Equatable協議”   如果有多個需要約束的協議則在Eqatableh

 where T:類型,T:類型....

協議的關聯類型修飾符  typealias

  定義協議時我們無法聲明泛型  所以在協議中泛型寫法變了一下

protocol Containter {
    typealias Element
    mutating func push(e: Element)
    mutating func pop()-> Element
}

實現該協議

struct MyStack: Containter{
    //   typealias Element = Int
    
    var containers = [Int]()
    mutating func push(e: Int) {
        containers.append(e)
    }
    mutating func pop() -> Int {
        return containers.removeLast()
    }
}

實現時經過swift類型推斷 實現為 Element = Int

實現后更改泛型名稱也是可以的

struct Stack<Element,Com>: Containter {
    //按照當前的實現,下面的代碼由於類型推斷,可以省略
    //typealias Element = E
    var containers = [Element]()
    var com=[Com]()
    mutating func push(e: Element) {
        containers.append(e)
    }
    mutating func pop() -> Element {
        return containers.removeLast()
    }
    
}

擴展協議時的約束以及協議關聯類型的使用

//定義兩個協議MM,NN
protocol MM {
    
}
protocol NN : MM{
    
}
//分別實現協議MMClass,NNClass
class MMClass: MM {
    
}
class NNClass: NN {
    
}
//定義f泛型協議Container
protocol Container {
    typealias ItemType
}
//擴展泛型協議Container的泛型  使其受MM協議約束
extension Container where   ItemType: MM {
    var b: Int {return 5}
}
//擴展泛型協議Container的泛型  使其受NN協議約束
extension Container where   ItemType: NN {
    var b: Int {return 6}
}
//TestTest類實現Container協議
class TestTest: Container {
    typealias ItemType = MMClass //如果這里改為MMClass,那么aaaa.b輸出結構是5
}
class TestTest2: Container {
    typealias ItemType = Int //若泛型類型的值不滿足任何一個協議則無法訪問b屬性
}
let aaaa  = TestTest()
aaaa.b
let bbbb = TestTest2()
bbbb.b//報錯

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM