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
}
這樣不僅在強制轉型時可讀性不佳,而且傳遞參數時無法限定可以傳遞的型別。假設已知參數的可能型別有 String
和 Date
,上面的原始碼可以利用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 來封裝數值,不僅提升可讀性,也可以限定傳遞的型別,避免傳遞不能處理的型別的狀況。此外,若未來需要擴充可傳遞的型別,也可以新增新的 case
至 enum
宣告中。
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.