Swift泛型協議的N種用法


  They said "you should learn a new language every year," so I  learned Swift. Now  I  learn a new language every two weeks!

  這個笑話絕對是我看過的Swift被黑的最慘的一次!所以今天我們來學習一下Swift的泛型。

  Swift的泛型有點奇怪,針對Class和Function,都是通過<Type>來定義,和C#一摸一樣,同樣也有where關鍵字進行約束。

func swapTwoValues<T>(inout a: T, inout _ b: T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

class CanPrintBase<T> {
    func PrintType(output: T) -> Void {}
}

  但是面對Interface也就是Swift里的Protocol,需要使用associatedtype關鍵字來定義泛型:

protocol CanPrint {
    
    associatedtype E
    
    func PrintType(output: E) -> Void
}

  那要怎么去實現這個接口呢?通常是這樣子的:

class TypePrinter0 : CanPrint{
    
    typealias E = String
    
    func PrintType(output: E) {
        print(type(of:output))
    }
}

let print0 = TypePrinter0()
print0.PrintType(output: "String Type")

  然后就會在output窗口打印“String”

  阿西吧!這么奇怪的語法簡直不能忍!就不能用<Type>來寫嗎?

  曲線救國的話,我們可以考慮模擬一個抽象類class CanPrintBase<T>,通過繼承來實現同樣的效果:

class TypePrinter3: CanPrintBase<String>{
    
    override func PrintType(output: String){
         print(type(of:output))
    }
}

let print3 = TypePrinter3()
print3.PrintType(output: "String Type")

  那么我們像C#一樣直接在類定義的時候通過占位符的方式可以嘛?

//This one cannot work!
class TypePrinter1<E: String> : CanPrint{
   
    func PrintType(output: E) {
        print(output)
    }
}

  錯誤提示為:Inheritance from non-protocol, non-class type 'String'。也就是說如果是class類型的話就可以:

public class SomeType {}

class TypePrinter2<E: SomeType> : CanPrint{

    func PrintType(output: E) {
        print(output)
    }

}

let print2 = TypePrinter2()
print2.PrintType(output: SomeType())

  反之我們也可以寫成這樣

class TypePrinter5 : CanPrint{
    
    typealias E = SomeType
    
    func PrintType(output: E) {
        print(output)
    }
}

let print5 = TypePrinter5();
print(type(of: print5))
print(type(of: print2))

  將類型打印出來的話,分別是TypePrinter5和TypePrinter2<SomeType>,也就是說這兩種寫法得到的類型是完全不一樣的。

  呵呵也是蠻妖的嘛,還可以把類型的具體定義留到使用時再聲明:

class TypePrinter4<E> : CanPrint{
    
    func PrintType(output: E) {
        print(output)
    }
}
let print4 = TypePrinter4<SomeType>()
print4.PrintType(output: SomeType())

let print6 = TypePrinter4<String>()
print6.PrintType(output: "I am a String")

  這一點又和C#傻傻分不清楚了。

  本篇實在是蠻無聊的糾纏與Swift泛型協議的語法,如孔乙己般嘗試了回字的N種寫法。至於為什么Swift要這么設計,我們下一篇可以嘗試和C#對比看看。

  GitHub:

  https://github.com/manupstairs/LearnSwift/tree/master/GenericProtocolTest

 

 


免責聲明!

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



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