为Swift中的Optional提供默认值?

时间:2014-06-07 17:46:17

标签: swift optional

在Swift中处理选项的习惯用法似乎过于冗长,如果您想要做的就是提供一个默认值,如果它没有:

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的可选基本相同)为此目的使用方法getOrElse

val myValue = optionalValue.getOrElse(defaultValue)

我错过了什么吗?斯威夫特有一个紧凑的方式吗?或者,如果失败,是否可以在Optional的扩展名中定义getOrElse

5 个答案:

答案 0 :(得分:251)

<强>更新

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方法

注意:我开始moduleor上添加Optional这样的常见帮助,以便迅速添加。

答案 1 :(得分:23)

截至2014年8月,Swift拥有合并运算符(??)。例如,对于可选的String myOptional,您可以编写:

result = myOptional ?? "n/a"

答案 2 :(得分:3)

如果你写了:

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

答案 3 :(得分:2)

以下似乎有效

extension Optional {
    func getOrElse<T>(defaultValue: T) -> T {
        if let value = self? {
            return value as T
        } else {
            return defaultValue
        }
    }
}

然而,投射value as T的需要是一个丑陋的黑客。理想情况下,应该有一种方法断言T与Optional中包含的类型相同。就目前而言,根据给予getOrElse的参数键入推理集T,如果这与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

答案 4 :(得分:0)

如果你想用一个字符串来做到这一点,你可以这样做..

string1 = string2.isEmpty ? "Default Value":string2