Swift 可选类型语法
Posted
技术标签:
【中文标题】Swift 可选类型语法【英文标题】:Swift Optional Type Syntax 【发布时间】:2014-06-11 19:10:19 【问题描述】:根据 Apple 的 Swift 指南,当您拥有以下 Array 和以下函数来搜索 Array 时:
let namesArray = ["John", "Lisa", "Bill", "Jennifer"]
// Note this function is set-up to return an OPTIONAL Int:
func findName (personName:String, arrayToSearchIn:String[]) -> Int?
for (indexOfName, nameValue) in enumerate(arrayToSearchIn)
if nameValue == personName
return indexOfName
return nil
...因此您可以捕获此函数返回的 Optional Int - 然后检查其是否为 nil
- 以下列方式:
let nameIndex: Int? = findName("Lisa", arrayToSearchIn: namesArray)
if nameIndex
println("found \(namesArray[nameIndex!])")
else
println("NOT found")
这一切都很好 - 但他们的下一个示例,他们通过将 2 个语句合并为一个来简化代码 - 让我感到困惑,因为他们突然放弃了可选的“?”和 ”!”从他们的语法来看:
if let nameIndex = findName("Lisa", arrayToSearchIn: namesArray)
println("found \(namesArray[nameIndex])")
而且效果很好。
那么为什么在第一个示例中nameIndex
被声明为“?” - 像这样:
nameIndex:Int?
并且使用“!”进行强制解包
[nameIndex!]
但在第二个示例中,“?”都不是。或者 ”!”一个在语法中使用?
【问题讨论】:
【参考方案1】:if let
中声明的处理是特殊的;应该将其视为自己的语言结构(而不是if
和let
的简单组合)。在
if let nameIndex = findName("Lisa", arrayToSearchIn: namesArray)
println("found \(namesArray[nameIndex]")
nameIndex
的类型不需要表达,因为可以推断为findName()
的返回类型Int?
。在if let ...
的主体中,nameIndex
的值未绑定到 可选,因此不需要展开 - 值将是 Int
。
下面是如何处理if let
绑定的示例。请注意,类型的显式声明基本上被忽略了:
> func test () -> Int? return 111
> if let x : Int? = test () return x
$R6: Int? = 111
> if let x : Int = test () return x
$R7: Int = 111
> if let x = test () return x
$R8: Int = 111
但如果您尝试在 if let
之外变得如此“灵活”,则会从编译器中得出错误:
> let y : Int = test ()
<REPL>:33:15: error: value of optional type 'Int?' not unwrapped;
did you mean to use '!' or '?'?
【讨论】:
(抱歉编辑)所以我明白你所说的不需要显式声明nameIndex
的类型,因为类型推断会自动解决这个问题 - 但不应该这适用于两种情况吗?为什么在第一种情况下我们 do 必须指定我们想要一个 Optional 并且我们想要强制解包它 - 但在第二种情况下,我们没有截断的 if let
语句这样做?
这是因为 if let
正在通过将 nameIndex
绑定到它的实际值来为您解包。
@sirab333:在您的第一个代码中,nameIndex
的类型为 Int?
。您可以显式指定类型或让它推断它;两者都可以。在您的第二个代码中,nameIndex
的类型为 Int
。同样,您可以明确指定它或让它推断它。因为在第一种情况下它是Int?
,所以它需要被解包。在第二种情况下,它已经是Int
。
@newacct:这并没有加起来:在这两种情况下,nameIndex
最终都被分配了函数findName
返回的值——它被明确声明为返回一个可选的Int?
,不是常规的 Int。所以在这两种情况下,nameIndex
also 最终不会是 Int?
类型 - 要么因为它也被明确声明为这样,要么因为它会被 推断 鉴于它捕获了函数返回的Int?
?或者,您是说 any var 声明为常规 var 而不是可选的,自动 强制解开分配的任何内容?
@sirab333:在第二种情况下,nameIndex
不是“分配了函数 findName 返回的值”。它是特殊的if let
语法。这与执行let
然后测试变量不同。在if let foo = bar
中,如果bar
的类型为T?
,则foo
的类型为T
。仅当bar
不是nil
时才分配foo
,然后才解包为foo
。【参考方案2】:
?
是显式声明可选类型的运算符。 !
是强制解包可选的运算符。示例中的语法是一种特殊的 Swift 简写,用于在一个简洁的行中检查和展开。它说,“将nameIndex
分配给findName(...)
的结果,如果不是nil
,则运行以下代码:...”
【讨论】:
感谢您花时间回答这个问题,但恐怕您误解了我的问题。我不是在问?
和 !
做什么。我知道他们在做什么——而且我完全明白这里使用的速记。我在问为什么?
和!
必须在第一个示例中使用,而不是在第二个速记示例中。似乎类型推断应该适用于两者,而不是只适用于一个,而不是另一个。有什么想法吗?
我不知道类型推断在第一个示例中是如何工作的。如果您完全删除该类型会发生什么?我相信如果你将它声明为Int
而不是Int?
,你会得到一个错误,但是如果你完全放弃这个类型怎么办:let nameIndex = findName("Lisa", arrayToSearchIn: namesArray)
?以上是关于Swift 可选类型语法的主要内容,如果未能解决你的问题,请参考以下文章