1. 程式人生 > >Swift 型別的檢査與轉換(is,as,AnyObject,Any)

Swift 型別的檢査與轉換(is,as,AnyObject,Any)

is和as

型別轉換 可以判斷例項的型別,也可以將例項看做是其父類或者子類的例項。

型別轉換在 Swift 中使用 isas 操作符實現。這兩個操作符提供了一種簡單達意的方式去檢查值的型別或者轉換它的型別。

直接上程式碼,首先定義幾個類:

//型別的檢査與轉換
class Fruit{

    let placeOfOriginal: String
    init(placeOfOriginal: String){
        self.placeOfOriginal = placeOfOriginal
    }
}

class Apple:Fruit{

    func desCription(){
        print("蘋果的原產地\(placeOfOriginal)")
    }
}

class Orange:Fruit{
 
    func desCription(){
        print("橘子的原產地\(placeOfOriginal)")
    }
}

func testOne(){
    
        //定義了五個水果
        let apple1 = Apple(placeOfOriginal: "北京")
        let apple2 = Apple(placeOfOriginal: "上海")
        let apple3 = Apple(placeOfOriginal: "深圳")
        let orange1 = Orange(placeOfOriginal: "成都")
        let orange2 = Orange(placeOfOriginal: "廣州")
        
        let basket = [apple1,apple2,apple3,orange1,orange2]
        
        for fruit in basket{
        
            //1:如果想要使用子類Apple和Orange的方法那麼久必須使用 as操作符進行型別轉換,轉換為對應的型別.
            if let apple = fruit as? Apple{
                apple.desCription()
            }else if let orange = fruit as? Orange{
                orange.desCription()
            }
        }
        
        //如果我們想知道籃子裡有多少蘋果有多少橘子,所以惡魔需要使用is操作符,來挨個檢測這些水果類例項,到底是蘋果還是橘子.
        var appleCount = 0
        var orangeCount = 0
        for fruit in basket{
            
            //1:如果想要使用子類Apple和Orange的方法那麼久必須使用 as操作符進行型別轉換,轉換為對應的型別.
            if  fruit is Apple{
                 appleCount++
            }else if fruit is Orange{
                 orangeCount++
            }
        }
        
        print("水果籃子裡有:\(appleCount)個蘋果和\(orangeCount)個橘子")
        //水果籃子裡有:3個蘋果和2個橘子
 }
總結 is和as的用法:

is操作符是一個型別檢査操作符,在Swift中,對它的定義是:檢測一個例項是不是特定類的子型別,如果是,則該操作符返回true,如果不是,則返回false.在使用is操作符時,需要注意:is操作符的左運算元只能是一個父類的例項,而右操作符只能是一個子類型別,不滿足該規則的程式碼會導致編譯錯誤.
        比如:用一個Apple的例項apple1,去看它是不是一個Orange例項,或者使用 apple1例項看是不是Apple的例項: 

       
 
    as操作符是一個型別轉換操作符,主要用於例項在子類和父類間的轉換.它有兩個版本,分別是帶問號的版本(as?)和不帶問號的版本(as),我們把它們分別稱為"as的可選格式"和"as的強制解封格式".其中 as的可選格式返回一個子類的可選型別,成功時該可選型別的值為子類例項,失敗時該可選型別的值為nil.而as的強制解封格式則會強制執行轉換操作,如果失敗將會導致執行時錯誤

,這裡需要注意:
        1:如果你不是確定你的型別轉換是否成功,務必使用as?(as的可選格式),然後通過nil判斷來檢査成功與否.
        2:如果你非常確定這個轉換一定成功,就使用 as(as的強制解封格式),但要明白使用as的強制解封格式是需要承擔代價的.
        在使用 as操作符時,需要注意可選格式和強制解封格式在使用上的差別,其中 as?操作符嚴格要求坐運算元只能夠為嚴格父型別的例項,而右運算元只能是為嚴格子型別,而 as操作符的限制缺相對要寬鬆.

AnyObject和Any

Swift為不確定型別提供了兩種特殊類型別名:

AnyObject可以代表任何class型別(即類型別)的例項。
Any可以表示任何型別,包括方法型別(function types)。用來修飾任意型別的例項,包括AnyObject修飾的例項.



注意:
只有當你明確的需要它的行為和功能時才使用Any和AnyObject。在你的程式碼裡使用你期望的明確的型別總是更好的.

AnyObject型別

//AnyObject任意例項型別
class Evil{

    var name = ""
}

class Angel{

    var name = ""
}

class Folk{

    var name = ""
}
func testTwo(){
      
        var hiter = Evil()
        hiter.name = "希特勒"
        
        var chenGuanBiao = Angel()
        chenGuanBiao.name = "陳游標"
        
        var laoMa = Folk()
        laoMa.name = "老碼"
        
        var buddhism = [String:AnyObject]()
        buddhism = ["悟空":hiter, "悟靜": chenGuanBiao, "悟能":laoMa]
        
        for (key, value) in buddhism{
        
            if let v = value as? Evil{
             
                print("惡魔:\(v.name) 法號:\(key)")
            }else if let v = value as? Angel{
                
                print("天使:\(v.name) 法號:\(key)")
            }else if let v = value as? Folk{
            
                print("農民:\(v.name) 法號:\(key)")
            }else{
            
                print("眾生平等,不問背景!")
            }
        }
        
        /*
        
        天使:陳游標 法號:悟靜
        惡魔:希特勒 法號:悟空
        農民:老碼 法號:悟能
        
        對於佛門我們用名為buddhism的字典,其型別為[String:AnyObject].也就是說佛門誰都可以進,不管你是惡人希特勒還是好人表格還是農民,這些都沒有統一的父子類關係,但是都可以放到佛門這個字典裡,因為它的型別是AnyObject,但是key是String型別,因為進入佛門的人都要一個法號.比如老碼就是悟能.
        在訪問字典裡的元素的時候,需要分別處理,因為AnyObject沒有辦法具體到哪個例項.
        */
        
    }

 

Any型別 

func testThree(){
    
       //Any 其實Any是AnyObject的總類,完全覆蓋AnyObject.
        var things = [Any]()
        
        func getSalarySummary(month: Int) -> Double{
            
            return Double(month * 1000)
        }
        
        things.append(0)
        things.append(0.0)
        things.append(50)
        things.append(4.1527)
        things.append("hello jack")
        things.append((3.0,6.0))
        things.append(getSalarySummary)
        
        for thing in things{
        
        switch thing{
            
            case 0 as Int:
                       print("這是一個整形!")
            case 0 as Double:
                       print("0是一個Double型別!")
            case let someInt as Int:
                       print("\(someInt) 是一個整形!")
            case let someDouble as Double where someDouble > 0:
                       print("\(someDouble)是一個正數!")
            case is Double:
                       print("其他Double型!")
            case let someString as String:
                       print("字串\(someString)型")
            case let (x,y) as (Double, Double):
                       print("座標(x,y)是\(x),\(y)")
            case let getSalarySummaryFunction as Int -> Double:
                       print("總收入為: \(getSalarySummaryFunction(12))")
            default:
                      print("其他值!")
            }
        }
        
        /*
        
        這是一個整形!
        0是一個Double型別!
        50 是一個整形!
        4.1527是一個正數!
        字串hello jack型
        座標(x,y)是3.0,6.0
        總收入為: 12000.0
        
        注意:
        在一個switch語句的case中使用強制形式的型別轉換操作符(as, 而不是 as?)來檢查和轉換到一個明確的型別。在 switch case 語句的內容中這種檢查總是安全的。
        */
    }