麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

Swift3.0 泛型<T>

2019-11-14 10:12:05
字體:
供稿:網(wǎng)友
泛型能夠讓開發(fā)者編寫自定義需求已經(jīng)任意類型的靈活可用的的函數(shù)和類型。能夠讓我們避免重復(fù)的代碼。用一種清晰和抽象的方式來表達(dá)代碼的意圖。

1.泛型解決的問題

下面是一個(gè)非泛型的例子
func swapTwoIntValue(a: inout Int, b: inout Int){    let tempValue = a    a = b    b = tempValue}
這個(gè)函數(shù)用來交換兩個(gè)整形的數(shù)值
var a = 1var b = 2swapTwoIntValue(a: &a, b: &b)PRint(a, b)//2,1
對(duì)于這個(gè)例子,假如我們想交換兩個(gè)Double類型、或者是其他類型的值,就需要針對(duì)每個(gè)類型寫不同的方法,只是參數(shù)類型不同。為了解決這個(gè)問題,Swift提供了泛型,幫助我們來解決這個(gè)問題。
注意:Swift是安全的語言,不允許兩個(gè)不同類型互換值

2.泛型函數(shù)

下面是一個(gè)泛型的函數(shù)
func swapTwoValue<T>(a: inout T, b: inout T){    let tempValue = a    a = b    b = tempValue}
這個(gè)函數(shù)主體、功能跟上面的例子類似,用來交換兩個(gè)同樣類型的值,但是這個(gè)函數(shù)用 T 占位符來代替實(shí)際的類型。并沒有指定具體的類型,但是傳入的a ,b 必須是同一類型T。在調(diào)用這個(gè)函數(shù)的時(shí)候才能指定 T 是那種具體的類型。還有函數(shù)名后跟的那個(gè) <T> 是函數(shù)定義的一個(gè)占位類型名,并不會(huì)查找T的具體類型
swapTwoValue(&oneInt, b: &twoInt)print("oneInt:/(oneInt),twoInt:/(twoInt)") // oneInt:3,twoInt:4var oneStr = "hello"var twoStr = "world"swapTwoValue(&oneStr, b: &twoStr)print("oneStr:/(oneStr),twoStr:/(twoStr)")// oneStr:world,twoStr:hellovar oneDouble = 10.01var twoDouble = 20.02swapTwoValue(&oneDouble, b: &twoDouble)print("oneDouble:/(oneDouble),twoDouble:/(twoDouble)")// oneDouble:20.02,twoDouble:10.01
這個(gè)例子用泛型完美的解決了上述的問題,只需要定義一個(gè)泛型函數(shù),只要保證 傳入的兩個(gè)參數(shù)是同一個(gè)類型,就不用根據(jù)傳入?yún)?shù)的類型不同而寫不同的方法。

3.類型參數(shù)

在上面的泛型函數(shù)例子中,占位符T是類型參數(shù)的一個(gè)例子。類型參數(shù)指定并命名一個(gè)占位符類型,并用<>包裹,放在函數(shù)名后面。一旦一個(gè)參數(shù)類型確定,就可以指定參數(shù)類型,或者返回值的類型,還可以用作函數(shù)體的注釋類型。在調(diào)用的時(shí)候會(huì)被實(shí)際的類型替代,如傳遞的是Int,就替換為Int,如果傳入的是Double類型就替換為Double等等

4.命名類型參數(shù)

上面的泛型例子的 T,只是一個(gè)描述性的名字,通常用單一的字母來命名,例如:T、U、V等。T代表只是一個(gè)占位符,命名規(guī)則同駝峰命名法

5.泛型類型

除了定義泛型函數(shù),還可以定義泛型類型。如Array,Dictionary的用法
下面展示一個(gè)非泛型版本棧
struct IntStack {    var items = [Int]()    mutating func push(item: Int) {        items.append(item)    }    mutating func pop(item: Int) -> Int {        return items.removeLast()    }}
這個(gè)是一個(gè)泛型版本的棧
struct Stack<T> {    var items = [T]()    mutating func push(item: T) {        items.append(item)    }    mutating func pop(item: T) -> T {        return items.removeLast()    }}
首先在函數(shù)名后面加<泛型類型名>,<>里面表明類型參數(shù)名。然后在函數(shù)主體里面完成跟非泛型棧類似的功能。這樣這個(gè)泛型結(jié)構(gòu)體就不只能壓棧Int類型的值,還可以是其它類型
var stack = Stack<String>() //要在類型名后面加<類型名>stack.push("uno")stack.push("dos")stack.push("tres")stack.push("cuatro")print(stack.pop()) // cuatro

6.擴(kuò)展一個(gè)泛型類型

可以擴(kuò)展一個(gè)泛型類型,給這個(gè)泛型類型添加屬性、方法、下標(biāo)等。
extension Stack{    //給泛型Stack擴(kuò)展一個(gè)計(jì)算型屬性topItem,返回最上面的item    var topItem: T? {        return items.isEmpty ? nil : items[items.count-1]    }}

7.類型約束

在上面的SwapTwoVlues 和 Stack中,可以作用任何類型。但是也可以添加一個(gè)約束,比如指定一個(gè)類型必須采納某協(xié)議或者是指定類等。在Swift中(Bool,Int,Doube,String默認(rèn)都是哈希的),Dictionary的鍵就需要必須是可哈希的,方便字典查找是否已包含某個(gè)鍵的值。
類型約束語法
可以在類型參數(shù)名后面加一個(gè)類型或者協(xié)議名,通過冒號(hào)隔開,多個(gè)類型參數(shù)之間用逗號(hào)隔開
func somFuntion<C:NSObject, P: NSObjectProtocol>(someClass: C, someProtocol: P){    //這里用NSObject和NSObjectProtocol做例子}
在定義的這個(gè)函數(shù)中,有兩個(gè)類型約束,第一次類型參數(shù)C代表是某個(gè)類,第二個(gè)參數(shù)P代表某個(gè)協(xié)議。

類型約束實(shí)踐

這個(gè)非泛型類型的方法用來查找某個(gè)字符串是否在字符數(shù)組中,存在返回index
func findStrInArray(_ array: [String], strToFind: String) -> Int?{    for (index,value) in array.enumerated(){        if strToFind == value{            return index        }    }    return nil}下面這是針對(duì)上面非泛型方法泛型版本的方法
func findIndex<T: Equatable> (_ array: [T], _ valueToFind: T) -> Int? {    for  (index,value) in array.enumerated(){        if value == valueToFind { //如果沒指定S:Equatable 這句話會(huì)編譯不通過            return index        }    }    return nil}
在這個(gè)泛型例子中,不是所有的類型都可以 用 == 來比較的,所有必須指定泛型類型參數(shù)的約束為 Swift提供的 Equatable 協(xié)議,這表示T代表的類型必須是支持 Equatable 協(xié)議的。所有的Swift標(biāo)準(zhǔn)類型默認(rèn)都是支持Equatable協(xié)議的.
let value = findIndex([3.14159, 0.1, 0.25], 9.3)// doubleIndex 類型為 Int?,其值為 nil,因?yàn)?9.3 不在數(shù)組中l(wèi)et stringIndex = findIndex(["Mike", "Malcolm", "Andrea"], "Andrea")// stringIndex 類型為 Int?,其值為 2

8.關(guān)聯(lián)類型

在定義協(xié)議的時(shí)候,有時(shí)候用一個(gè)或者多個(gè)關(guān)聯(lián)類型作為定義協(xié)議的一部分,關(guān)聯(lián)類型作為協(xié)議的一部分,為某個(gè)類型提供了一個(gè)占位符,其實(shí)際類型會(huì)在采納的時(shí)候被指定。并用關(guān)鍵字typealias 關(guān)鍵字來指定關(guān)聯(lián)名

關(guān)聯(lián)類型實(shí)踐

下面定義一個(gè)協(xié)議,協(xié)議指定了一個(gè)關(guān)聯(lián)類型
protocol Container{    associatedtype itemType //聲明一個(gè)關(guān)聯(lián)類型    mutating func appended(item: itemType)    var count: Int{ get }    subscript(i: Int) -> itemType { get }}
下面是非泛型的版本采納 Container 協(xié)議
struct intStack: Container {    // IntStack 的原始實(shí)現(xiàn)部分    var items = [Int]()    mutating func push(item: Int) {        items.append(item)    }    mutating func pop() -> Int {        return items.removeLast()    }        // Container 協(xié)議的實(shí)現(xiàn)部分    mutating func appended(item: Int) {        self.push(item: item)    }    var count: Int {        return items.count    }    subscript(i: Int) -> Int {        return items[i]    }}下面是一個(gè)泛型版本的
struct genericStack<T>: Container{    // genericStack<T> 的原始實(shí)現(xiàn)部分    var items = [T]()    mutating func push(item: T) {        items.append(item)    }    mutating func pop() -> T {        return items.removeLast()    }        // Container 協(xié)議的實(shí)現(xiàn)部分    mutating func appended(item: T) {        self.push(item: item)    }    var count: Int {        return items.count    }    subscript(i: Int) -> T {        return items[i]    }}

通過擴(kuò)展一個(gè)存在類型來指定關(guān)聯(lián)類型

通過擴(kuò)展添加協(xié)議的一致性描述了如何利用一個(gè)已存在類型符合一個(gè)協(xié)議,這包括了使用關(guān)聯(lián)協(xié)議
Swift中的Array都滿足了Container協(xié)議的要求,意味著可以擴(kuò)展Array采納Container協(xié)議,你可以通過一個(gè)空擴(kuò)展來實(shí)現(xiàn)這點(diǎn).
extension Array :Container{    mutating internal func appended(item: Element) {}}
定義這個(gè)擴(kuò)展之后,可以用Array當(dāng)做Container類型使用。

9.Where子句

類型約束能夠讓我們?yōu)榉盒皖愋吞砑右恍┘s束和條件。為關(guān)聯(lián)類型添加一些約束也是很有必要的。可以在參數(shù)列表中使用where子句來為關(guān)聯(lián)類型添加約束。
下面的例子判斷兩個(gè)采納Container協(xié)議的類型是否所有的元素順序及值都相等。
func allItemsMatch<C1: Container,C2: Container>(someContainer: C1,_ anotherContainer: C2) -> Bool where C1.itemType == C2.itemType, C1.itemType: Equatable {    if someContainer.count != anotherContainer.count {        return false    }    for i in 0...someContainer.count-1{        if someContainer[i] != anotherContainer[i]{            return false        }    }    return true}
這個(gè)泛型函數(shù)在類型參數(shù)里面添加了where子句約束,C1,C2都必須是采納Container協(xié)議的類型,并且C1、C2的泛型類型必須相同,而且C1的泛型類型必須是采納Equatable的。
var stackOfStrings = genericStack<String>()stackOfStrings.appended(item: "uno")stackOfStrings.appended(item: "dos")stackOfStrings.appended(item: "tres")var arrayOfStrings = ["uno", "dos", "tres"] //array類型的滿足Container類型,參考上面的extension Arrayif allItemsMatch(stackOfStrings, arrayOfStrings) {    print("All items match.")} else {    print("Not all items match.")}//結(jié)果是:All items match.

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 黄a大片| 国产精品亚洲综合 | 欧美成人小视频 | 精品一区二区免费视频视频 | 欧美黄色视屏 | 337p日本欧洲亚洲大胆精蜜臀 | 久久成人精品视频 | 在线播放一区二区三区 | 久久影院在线观看 | 亚洲精中文字幕二区三区 | 久久999精品| 久久综合久久综合久久综合 | 羞羞的视频在线免费观看 | 亚洲免费在线看 | 久久久看| 看免费黄色一级片 | 欧美成人一区二区三区 | 成人免费一区二区三区在线观看 | 亚洲免费视频一区 | 黄色免费播放网站 | 国人精品视频在线观看 | 国产视频精品在线 | 羞羞的网站 | 国产毛片在线看 | 毛片中文字幕 | 亚洲精品动漫在线观看 | 欧美成人鲁丝片在线观看 | 久久久久久艹 | 国产精品.com | 国产精品久久久久久久久粉嫩 | 成年片在线观看 | 国产精品视频在线观看免费 | 一区视频 | 日日操操 | 毛片视频大全 | 亚洲一级成人 | 羞羞视频免费观看入口 | 国产精品久久久久久久久久大牛 | 鲁丝一区二区二区四区 | 国产精品久久久久久久hd | www久久久久久 |