1. 程式人生 > >Swift中協議與泛型的應用

Swift中協議與泛型的應用

1.方法的泛型

 //泛型約束(冒號後邊跟class或者協議,傳入的引數someT和someU必須是遵循該協議或類---(NAArray類,Comparable協議))
    func someFunction<T:NSArray, U:Comparable>(someT: T, someU: U) {
        // 這裡是泛型函式的函式體部分
    }
    
    
    func comparTwo<T:Comparable>( _ a:T,_ b:T) -> Bool {
        return a>b
    }

與OC中的id有點類似,只是可以遵循協議或者指定型別

 

2.struct的泛型

struct Stack<Element> {
    var items = [Element]()
    mutating func push(_ item: Element) {
        items.append(item)
    }
    mutating func pop() -> Element {
        return items.removeLast()
    }
}
 
var stackOfStrings = Stack<String>()
print("字串元素入棧: ")
stackOfStrings.push("google")
stackOfStrings.push("runoob")
print(stackOfStrings.items);
 
let deletetos = stackOfStrings.pop()
print("出棧元素: " + deletetos)
 
var stackOfInts = Stack<Int>()
print("整數元素入棧: ")
stackOfInts.push(1)
stackOfInts.push(2)
print(stackOfInts.items);

(1)struct也可以使用泛型,當呼叫結構體的時候可以指定泛型的具體型別

//協議
 protocol Container {
    //associatedtype 關鍵字來指定關聯型別(就是定義一個泛型名字叫ItemType,這個等價於下邊的Element,都是一個泛型)
    associatedtype ItemType
    //新增一個新元素到容器裡
    mutating func append(item:ItemType)
    //獲取容器中元素的數
     var count: Int{get}
    //通過索引值型別為 Int 的下標檢索到容器中的每一個元素
    //下標指令碼是系統提供的可以對struct或者enum或者陣列等重寫的一個屬性
    subscript(i:Int) -> ItemType {get}
    
    //不一定是一維的,也可以是二維的
//    subscript(row: Int, col: Int) -> Double {
//        get
//    }
}


//Stack 遵循Container協議, (Element可以設定遵循某個協議)(這個協議可以寫在extension中的where裡)
struct Stack<Element>:Container {
    
    var items = [Element]()
    mutating func push(item:Element){
        items.append(item)
    }
    
    mutating func pop(item:Element){
        items.removeLast()
    }
    
    //協議部分
    mutating func append(item: Element) {
        self.push(item: item)
    }
    
    var count: Int{
        return items.count
    }
    
    subscript(i: Int) ->Element{
        return items[i]
    }
    
    
}



//where是對Stack傳入的元素的型別約束,必須遵循可以進行等於比較的協議(傳入陣列就不行),其實也可以在Stack定義的時候讓元素遵循某個協議,這個協議的範圍只是在呼叫這個擴充套件方法裡,上邊的push元素不遵循
extension Stack where Element:Equatable{
    func isTop(item:Element) -> Bool {
        guard let topItem = items.last else {
            return false
        }
        
        return topItem == item
    }
}


(2)呼叫Stack

func one(){
        var bbb = Stack<String>()
        bbb.push(item:"google")
        bbb.push(item:"runoob")
        bbb.push(item:"taobao")
        
       
        
       let mm = bbb.isTop(item: "optional")
        print("istop==\(mm)")
        //元素列表
        print(bbb.items)
        print(bbb.count)
        
        var aaa = Stack<String>()
        aaa.push(item:"google")
        aaa.push(item:"runoob")
        aaa.push(item:"taobao")
}

(3)寫一個泛型遵循Container協議的方法,正好上述Stack遵循Container協議,可以把aaa和bbb作為引數傳進去

 func allItemsMatch<C1:Container,C2:Container>(containter1:C1,containter2:C2) -> Bool
            where C1.ItemType == C2.ItemType, C1.ItemType:Equatable
        {
            
            if containter1.count != containter2.count {
                return false
            }
            
            for i in 0..<containter1.count {
                if containter1[i] != containter2[i]{
                    return false
                }
            }
            
            return true
        }

呼叫方法

 if allItemsMatch(containter1: aaa, containter2: bbb) {
            print("aaa == bbb")
        }else{
            print("aaa != bbb")
        }

補充:

subscript是系統提供的,通常情況下,我們在使用陣列(Array)或字典(Dictionary)時會使用到下標。其實在Swift中,我們還可以給類、結構、列舉等自定義下標(subscript)。

subscript例子:https://blog.csdn.net/sinat_27706697/article/details/47122137

 

整合的程式碼加自己的理解,參考文章:http://www.runoob.com/swift/swift-generics.html