2016-08-28 45 views
1
let sum1 = {(a:Int, b:Int) -> Int in return a + b} 
let sum2 = {(a:Float, b:Float) -> Float in return a + b} 

var cl = [sum1, sum2] 

爲什麼sum1sum2不能添加到數組中? 我知道sum1需要兩個Ints返回一個Int,sum2需要兩個Floats返回一個Float,但是一個數組可以添加兩個不同類型的對象,例如let foo = [12, "12"]是有效的。iOS swift爲什麼兩種封閉方式無法添加到陣列中

+1

是關於陣列中的類型或的缺失參數的錯誤閉包例如'let cl = [sum1(1,2),sum2(3.0,4.0)]'? – vadian

+0

它說:「表達式的類型是不明確的,沒有更多的上下文」 –

+0

如果你想持有封閉是真實的不同類型然後標記你的數組類型任何'let sum1 = {(a:Int,b:Int) - > Int返回a + b} let sum2 = {(a:Float,b:Float) - > Float in a + b} var cl:[Any] = [sum1,sum2]' –

回答

0

原因是每個閉包代表新類型,並且如果您的數組不是AnyAnyObject類型,則它只能包含一種類型的元素。這就是爲什麼你不能輕易將它們放在裏面。對於閉包,您需要使用類型Any,因爲閉包是結構類型。

+0

感謝您的回答!類型是AnyObject,我不能將閉包添加到數組 –

+1

嘗試類型任何。 AnyObject只能接受類,閉包而不是類表示,它是結構體。 – Volodymyr

+0

'''var cl = [Any]() cl.append(sum1) cl.append(sum2)''' 謝謝! 它只是明確地添加到類型爲'''Any''的數組 –

1

對於此問題,您使用[Any]的建議將編譯,但如果您在屬性中需要Any(或AnyObject),則幾乎總會有設計錯誤。 Any存在罕見的情況下,你真的必須繞過類型系統,但你通常會遇到許多令人頭疼的事情。

根據您的潛在目標的實際情況,這些類型的問題有很多類型安全的解決方案。最有可能的解決方案,如果你的目標是保持詮釋的方法從浮動的方法分離出來,是用一個枚舉:

enum Operator { 
    case int((Int, Int) -> Int) 
    case float((Float, Float) -> Float) 
} 

let sum1 = Operator.int {(a, b) in return a + b } 
let sum2 = Operator.float {(a, b) in return a + b} 

let cl = [sumop1, sumop2] 

Any意味着您可以扔掉它絕對任何東西,它是你的問題弄清楚什麼處理你在其中找到的隨機事物。編譯器不能幫助你,並且在某些情況下會積極地對抗你。您需要接受未定義的行爲,或者在整個地方添加precondition以在運行時檢查您沒有犯錯。

Operator是「OR」類型。 [Operator]是一組在Ints或Floats上運行的函數。這似乎意味着什麼,所以讓編譯器通過告訴它這是你的意思來幫助你。編譯器會在編譯時檢測錯誤,而不是在運行時崩潰。許多單元測試變得不必要,因爲整個類的錯誤是不可能的。有了正確的類型和編譯器的幫助下,您可以簡化cl到:

let cl: [Operator] = [.int(+), .float(+)] 

這是相當不錯的IMO。另一方面,如果目標是接受Ints和Floats,那麼你應該把它們包裝在NSNumber中,這兩者都可以工作。如果你想跟蹤哪個是整數的,哪些是花車讓你能夠更仔細地運用你的數學,你可以創建一個結構:

struct Number { 
    enum Kind { 
     case Int 
     case Float 
    } 
    let value: NSNumber 
    let type: Kind 
} 
相關問題