在 Swift 中处理可选项的习语似乎过于冗长,如果您只想在它为 nil 的情况下提供一个默认值:
if let value = optionalValue {
// do something with 'value'
} else {
// do the same thing with your default value
}
这涉及不必要的重复代码,或
var unwrappedValue
if let value = optionalValue {
unwrappedValue = value
} else {
unwrappedValue = defaultValue
}
这要求 unwrappedValue
不是常数。
Scala 的 Option monad(与 Swift 的 Optional 基本相同)为此使用了 getOrElse
方法:
val myValue = optionalValue.getOrElse(defaultValue)
我错过了什么吗? Swift 是否已经有一种紧凑的方式来做到这一点?或者,如果做不到这一点,是否可以在 Optional 的扩展中定义 getOrElse
?
更新
Apple 现在添加了一个合并运算符:
var unwrappedValue = optionalValue ?? defaultValue
在这种情况下,三元运算符是你的朋友
var unwrappedValue = optionalValue ? optionalValue! : defaultValue
您还可以为 Optional 枚举提供自己的扩展:
extension Optional {
func or(defaultValue: T) -> T {
switch(self) {
case .None:
return defaultValue
case .Some(let value):
return value
}
}
}
然后你可以这样做:
optionalValue.or(defaultValue)
但是,我建议坚持使用三元运算符,因为其他开发人员会更快地理解这一点,而无需研究 or
方法
注意:我创建了一个 module,以便在 Optional
上添加像 or
这样的常用助手到 swift。
截至 2014 年 8 月,Swift 拥有允许这样做的合并运算符 (??)。例如,对于可选 String myOptional 你可以写:
result = myOptional ?? "n/a"
如果你写道:
let result = optionalValue ?? 50
optionalValue != nil
然后 result
也将是 optional
,您将来需要打开它
但是你可以写运算符
infix operator ??? { associativity left precedence 140 }
func ???<T>(optLeft:T?, right:T!) -> T!
{
if let left = optLeft
{
return left
}
else { return right}
}
现在你可以:
let result = optionalValue ??? 50
当 optionalValue != nil
那么 result
将是 unwraped
以下似乎有效
extension Optional {
func getOrElse<T>(defaultValue: T) -> T {
if let value = self? {
return value as T
} else {
return defaultValue
}
}
}
但是需要强制转换 value as T
是一个丑陋的黑客。理想情况下,应该有一种方法可以断言 T
与 Optional 中包含的类型相同。就目前而言,类型推断集 T
基于给定给 getOrElse 的参数,然后在运行时失败,如果这与 Optional 不匹配并且 Optional 不为零:
let x: Int?
let y = x.getOrElse(1.414) // y inferred as Double, assigned 1.414
let a: Int? = 5
let b: Double = a.getOrElse(3.14) // Runtime failure casting 5 to Double
T
。这实际上覆盖了 Optional 中的现有 T
。你可以这样做: func getOrElse(defaultValue: T) -> T
然后 T 指的是可选的实际值类型,你不必类型检查它
T
吗? (不仅仅是基于惯例的简单假设)
Optional
,您将看到它被定义为 enum Optional<T>
如果您尝试使用 String 执行此操作,则可以执行此操作..
string1 = string2.isEmpty ? "Default Value":string2
unwrappedValue
的类型仍然是 Swift 1.2 中这种情况的可选类型:var unwrappedValue = optionalValue ? optionalValue! : defaultValue
(xcode 6 beta 4)。这有改变吗???
默认类型推断行为是它返回一个可选项,这通常不是您想要的。您可以将变量声明为非可选的,这很好用。