1. 程式人生 > >Swift開發中的Any和AnyObject 以及泛型的區別

Swift開發中的Any和AnyObject 以及泛型的區別


  • 我們都知道泛型、Any和AnyObject都是用於表示型別的隨意性,甚至還有OC中的id型別,但是它們具體有什麼不同呢?我們就來具體瞭解一下


    Any和AnyObject 

    概括來說AnyObject用於任何類(class)的例項,而Any可以用於表示任何變數,包括各種基本型別、值型別以及例項。而在swift中,列舉型別和結構體(例如Array和Dictionary)都屬於值型別,因而不能用AnyObject來進行修飾。
    舉個例子,在playground中輸入如下程式碼:


    import Cocoa
    import Foundation
    //測試程式碼
    class Car { //類 
    }
    struct Car { //結構體 屬於值型別
    }
    //Any測試程式碼 
    var arrAny = [Any]()
    arrAny.append(1) //正常
    arrAny.append(1.0) //正常
    arrAny.append("things") //正常
    arrAny.append(Car()) //正常
    arrAny.append(Trunk()) //正常
    //AnyObject測試程式碼
    var arrAnyObject:[AnyObject] = []
    arrAnyObject.append(Car()) //正常
    arrAnyObject.append(Trunk()) //報錯 

    按照上面的理論,Any可以表示任何的變數,而在AnyObject的例子中,由於Car 是一個類, 而Trunk屬於Struct,是一個值型別,所以新增Car例項成功,而新增Trunk時報錯。


    一切似乎很正常。但是,等一等,看看下面的程式碼


    arrAnyObject.append(1)
    arrAnyObject.append("str")
    arrAnyObject.append(1.0) 

    What?這些例子也是沒有報錯的。什麼情況?swift中這些量不是值型別嗎?
    不要著急,參考喵神的文章,這些變數分別被轉換成了NSNumber和NSString了。在 Swift 和 Cocoa 中的這幾個對應的型別是可以進行自動轉換的。當去掉import Foundation後,一切恢復正常,開始正常報錯啦!建議有想法的各位去看一下上面的這個文章。


    泛型 

    通常來講,泛型為類或者方法提供一個型別引數,以方便某個引數型別保持前後的一致性。基本概念就不多說了,看一下下面的例子


    func singleGenericFunc<T>(x: T ,y: Int)-> T {
    ......

    內部的實現就不說了,singleGenericFunc這個方法是接受某個型別的引數,和一個Int型,最後返回一個T型別。這裡泛型T 泛指任意型別。此處使用泛型主要有兩點作用:
    1 是保證了引數x的型別的隨意性。
    2 是保證了引數x的型別與整個方法的返回型別的統一性。


    當然一個方法或者型別裡面也可以有多個泛型。 T,U等任意字母或者單詞都可以,沒有具體的限制。例如:


    func multiGenericFunc<T,U,Element>(x:T, y:U, z:Element)-> Void {
    ......

    然後這和Any來修飾引數有什麼區別呢?看一下下面的對比:


    //泛型修飾
    func singleGenericFunc<T>(x: T ,y: Int)-> T {
    ......
    }
    //Any修飾
    func singleAnyFunc(x: Any,y:Int) -> Any {
    ......

    此處最大的不同是,singleGenericFunc中的引數x的型別與方法的返回型別是一致的。而singleAnyFunc中卻沒有這個特性。x與方法的返回型別都可以是任意值,不一定相同。
    這是由於泛型的型別檢查由編譯器負責,而Any修飾則避開了型別系統。
    綜合比較而言,應該儘量多使用泛型,少使用Any,以儘量轉換型別時發生的型別錯誤。


    參考文獻 http://swifter.tips/any-anyobject/