在这种情况下,为什么nil可以从非可选函数返回?

时间:2016-06-24 16:22:00

标签: swift null swift2

我在Playground中尝试以下代码,我不太明白为什么编译器在从非可选函数返回barnil时不会出错;以及当nilnil进行比较时为什么会这样做,并在声明foobar永远不会是nil时提供一条似乎不正确的错误消息。

编辑: 由于Optional也是Any,为什么不允许直接在nil中返回foo2

func foo() -> Any {
    let bar: String? = nil
    return bar
}

let foobar = foo()

if foobar == nil {

}

func foo2() -> Any {
    return nil
}

enter image description here

3 个答案:

答案 0 :(得分:5)

  

编辑:由于Optional也是Any,为什么不允许直接在foo2中返回nil?

因为nil没有自己的类型。它说什么都没有,但没有是什么?你必须选择那种类型:

func foo2() -> Any {
    return nil as String?
}

即使这是合法的:

func foo2() -> Any {
    return nil as Any?
}

但永远不要,永远不要这样做。 Any不是常规工具。它是类型系统处理特殊问题(如print)的最后一个逃生舱。当你将Any的魔力与Optional的魔力(特别是可选促销)混合在一起时,你会不断遇到混乱的错误并发现自己运行了错误的重载。

AnyObject确实出现了一些问题,但仅仅是因为与ObjC的桥接,ObjC使用了无类型的值(尽管这种情况正在改善,AnyObject变得越来越不常见)。但是在Swift代码中返回AnyObject仍然很少有意义。

答案 1 :(得分:4)

让我们准确解释代码中发生的事情:

func foo() -> Any {
    let bar: String? = nil
    return bar
}

nil是一个转换为String?(或Optional<String>)类型的文字,即Optional<String>.None

然后它被转换为Any。任何东西都可以投射到Any,包括选项。基本上你已经决定隐藏下划线类型。

然后foobar == nil。请注意,==是一项不会自动适用于所有类型的操作。与nil的比较是在可选类型上定义的,例如Optional<T>与另一个Optional<T>

在这种情况下,您有Anynil字面值。 Any本身不是可选的,因此您无法直接将其与nil进行比较。

您可以将其投射到可选的Any

let optionalFoobar = any as Any?

但是,现在变量包含一个双重可选Optional<Any>.Some(Optional<String>.None),与nil的比较不会起作用。

唯一可行的方法是:

if (foobar as Any?) as? String == nil {
    print("is nil")
}

简而言之,请勿使用Any,如果您使用的是非可选Any,请不要将可选类型存储到其中,它会变得非常复杂且无法使用实践。

答案 2 :(得分:0)

Any不是可选的,因此您无法与nil进行比较。如果要与nil进行比较,则返回类型必须是可选类型:Any?例如:

func foo() -> Any? {
    let bar: String? = nil
    return bar
}

let foobar = foo()

if foobar == nil {
    print("foobar is nil")
}