如何避免使用!使用此功能解压缩操作通常是一个不好的选择。
使用它的代码有什么更好的选择,使用它会使代码看起来更简单,因为if检查变量!被召唤永远不会是零,所以不能崩溃。
我的导师向我们介绍了bang(!)操作员,然后告诉我们再也不要使用它了。告诉我们为什么当然,如果可选项为nil,它将使我们的应用程序崩溃。
然而,我发现自己处于这样的情况下,爆炸操作员似乎是最简洁和安全的选择。
func fullName() -> String {
if middleName == nil {
return "\(firstName) \(lastName)"
}else{
return "\(firstName) \(middleName!) \(lastName)"
}
}
有没有更好的方法来做这样的事情?
此外,如果有人想知道,这里是完整的课程。
class CPerson{
var firstName: String
var middleName: String?
var lastName: String
init(firstName: String, middleName: String?, lastName: String) {
self.firstName = firstName
self.middleName = middleName
self.lastName = lastName
}
convenience init(firstName: String, lastName: String) {
self.init(firstName: firstName, middleName: nil, lastName: lastName)
}
func fullName() -> String {
if middleName == nil {
return "\(firstName) \(lastName)"
}else{
return "\(firstName) \(middleName!) \(lastName)"
}
}
}
我的导师说"如果我看到你使用爆炸操作员,我们就会打架" O_O
答案 0 :(得分:24)
使用if let
或guard
结构:
func fullName() -> String {
if let middleName = middleName {
return "\(firstName) \(middleName) \(lastName)"
} else {
return "\(firstName) \(lastName)"
}
}
func fullName() -> String {
guard let middleName = middleName else {
return "\(firstName) \(lastName)"
}
return "\(firstName) \(middleName) \(lastName)"
}
我已将guard
语句用于完整性,但正如其他人所评论的那样,这在错误/失败案例中更常用。
我还建议不要对字符串使用字符串插值。它们已经是字符串,不需要在新字符串中使用每个名称的description
。
考虑return firstName + " " + lastName
。有关字符串插值可能返回意外结果的情况,请参阅Difference between String interpolation and String initializer in Swift。
答案 1 :(得分:16)
从广义上讲,你的导师是正确的。绝对是在这种情况下。没有理由将这种特殊情况作为特殊情况并强制重复代码。
func fullName() -> String {
return [firstName, middleName, lastName] // The components
.flatMap{$0} // Remove any that are nil
.joined(separator: " ") // Join them up
}
这只是用空格连接名称的所有非零部分。这里的其他答案也很好,但是他们也不会扩展以添加更多可选部分(例如" Mr。" title或" Jr。"后缀)
(这是Swift3语法.Swift 2非常相似,而是joinWithSeparator(_:)
代替。)
答案 2 :(得分:5)
你所做的将会奏效,而且,一旦你知道它不是零,使用!是一种强制解开它的正确方法。
但是,Swift具有名为Optional Binding(https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html)的功能。
在你的情况下,它会是这样的:
func fullName() -> String {
if let middle = middleName {
return "\(firstName) \(middleName) \(lastName)"
} else {
return "\(firstName) \(lastName)"
}
}
可选绑定的作用是,正如Apple在上面的链接中所说,“你使用可选绑定来确定一个可选项是否包含一个值,如果是,则使该值可用作临时常量或变量”。因此,在括号内,您可以访问middle
,并可以将其用作已知的非零。
您还可以链接这些链接,以便您可以访问多个临时常量,而不需要链接if语句。您甚至可以使用where
子句来评估可选条件。再次来自Apple的上述文档:
if let firstNumber = Int("4"), secondNumber = Int("42") where firstNumber < secondNumber {
print("\(firstNumber) < \(secondNumber)")
}
答案 3 :(得分:2)
在展开可选变量之前,您必须检查nil
,否则如果变量包含nil
,您的应用就会崩溃。
检查可以通过以下几种方式执行:
if let
guard
if-else
完全使用哪一个取决于要求。
您只需替换此代码
即可if middleName == nil {
return "\(firstName) \(lastName)"
}else{
return "\(firstName) \(middleName!) \(lastName)"
}
通过
return "\(firstName)\(middleName != nil ? " \(middleName!) " : " " )\(lastName)"
OR
如果a包含值,您也可以使用 Nil coalescing operator (a ?? b)展开可选的a,如果a为n,则返回默认值b。
答案 4 :(得分:0)
在这种情况下,你的导师错了。你的功能绝对安全。 middleName不会在背后从零变为零。如果你发出一些拼写错误,你的函数可能会崩溃,并输入一个不同的变量而不是middleName的名称,但无论如何这将是一个错误,崩溃将导致你的错误。
但通常“如果让......”是处理这个问题的更好方法,因为它结合了测试和解包。
还有一些情况你不会说“如果它是零,它会崩溃,那是坏的”,但“如果它是零,那么我希望它崩溃”(通常因为你知道它只能是零,如果有的话代码中某处的错误)。在这种情况下 !完全符合你的要求。