Besides [String: Any]/除了 [String: Any] 之外

偶爾,我會遇見宣告成 [String: Any]的參數。

From time to time I encounter parameters declared as [String: Any].

雖然這樣的宣告提供了字典類別攜帶各種類別的值的彈性,但取值時卻常帶來麻煩。也許你曾讀到過類似的原始碼:

Though such declarations indeed provide the flexibility to carry all sorts of values through a dictionary, getting values from it is usually troublesome. Perhaps you’ve ever read something similar:

func doSomething(parameters: [String: Any]) {
for key in parameters.keys {
if parameters[key] is String {
let value = parameters[key] as! String
// do something with the casted value
}
if parameters[key] is Date {
let value = parameters[key] as! Date
// do something with the casted value
}
}
// and so on
}

這樣不僅在強制轉型時可讀性不佳,而且傳遞參數時無法限定可以傳遞的型別。假設已知參數的可能型別有 StringDate ,上面的原始碼可以利用enum 的 associated value 改寫成:

It’s not only bad for readability, and it cannot delimit allowing types of parameters’ values. Suppose the known types are String and Date. We can rewrite the code as follow, by leveraging the associated values ofenum :

enum MyParams {
case string(String)
case date(Date)
}
func doSomething(parameters: [String: MyParams]) {
for key in parameters.keys {
switch parameters[key]! {
case .string(let value):
// do something with the value
case .date(let value):
// do something with the value
}
}
// and so on
}

透過 enum 的 associated values 來封裝數值,不僅提升可讀性,也可以限定傳遞的型別,避免傳遞不能處理的型別的狀況。此外,若未來需要擴充可傳遞的型別,也可以新增新的 caseenum 宣告中。

Encapsulating values through enum’s associated values, it does not only improve readability but also delimit types allowed to pass through parameters, avoiding unsupported types of values to be passed to the function. On the other hand, when there are new types to be passed to the function through parameters, one can still add new case to the enum’s declaration easily.

--

--