SWIFT中的“未包装价值”是什么?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (14)

编辑

原始代码的输出与最终解决方案(在操场上测试)之间有细微的差别:

原码

Cezary 的解决方案

超类的属性在第二种情况下显示在输出中,而在第一种情况下则是空对象。

两种情况下的结果不都是一样的吗?

提问于
用户回答回答于

首先,了解什么是可选类型。可选类型基本上意味着变量可以nil.

例子:

var canBeNil : Int? = 4
canBeNil = nil

问号表示以下事实:canBeNil可以nil...

这样做是行不通的:

var cantBeNil : Int = 4
cantBeNil = nil // can't do this

要从变量中获取值(如果它是可选的)。这只意味着在结尾加一个感叹号。

var canBeNil : Int? = 4
println(canBeNil!)

代码应该如下所示:

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare!.sideLength

可以通过使用感叹号而不是问号来声明选项以自动展开。

例子:

var canBeNil : Int! = 4
print(canBeNil) // no unwrapping needed

因此,修复代码的另一种方法是:

let optionalSquare: Square! = Square(sideLength: 2.5, name: "optional square") 
let sideLength = optionalSquare.sideLength

编辑:

一个快速的游乐场比较:

在第一种和第二种情况下,对象不会被自动展开,所以会看到两个“层”({{...}}),而在第三种情况下,您只看到一个层({...}),因为对象正在自动展开。

第一种情况和第二种情况的区别是,如果下列情况发生,则后两种情况将给出一个运行时错误。optionalSquare设置为nil,使用第一种情况下的语法,可以这样做:

if let sideLength = optionalSquare?.sideLength {
    println("sideLength is not nil")
} else {
    println("sidelength is nil")
}
用户回答回答于

现有的正确答案很好,但我发现要完全理解这个问题,我需要一个很好的类比,因为这是一个非常抽象和奇怪的概念。

所以,让我帮助那些“正确的思维”(视觉思维)的开发人员,给出一个不同的视角,除了正确的答案。这里有一个很好的类比,对我有很大的帮助。

生日礼物包装类比

把选项看作是像生日礼物一样,用硬的,硬的,彩色的包装。

在打开礼物之前,你不知道包裹里是否有什么东西--也许里面什么都没有!如果里面有什么东西,它可能是另一个礼物,它也被包裹着,可能什么都不包含.甚至可以打开100个嵌套的礼物,最终发现除了包装什么都没有.

如果可选值不是nil,现在你发现了一个盒子某物。但是,特别是如果该值不是显式类型的,并且是一个变量而不是一个预定义常量,那么可能仍然需要打开盒子在你知道盒子里有什么东西之前,就像什么类型是的,或者是什么价值是。

这就是为什么在SWIFT中处理集合类型(字典和数组)的原因。

例如:

typealias presentType = [Int:Any?]

func wrap(i:Int, gift:Any?) -> presentType? {
    if(i != 0) {
        let box : presentType = [i:wrap(i-1,gift:gift)]
        return box
    }
    else {
        let box = [i:gift]
        return box
    }
}

func getGift() -> String? {
    return "foobar"
}

let f00 = wrap(10,gift:getGift())

//Now we have to unwrap f00, unwrap its entry, then force cast it into the type we hope it is, and then repeat this in nested fashion until we get to the final value.

var b4r = (((((((((((f00![10]! as! [Int:Any?])[9]! as! [Int:Any?])[8]! as! [Int:Any?])[7]! as! [Int:Any?])[6]! as! [Int:Any?])[5]! as! [Int:Any?])[4]! as! [Int:Any?])[3]! as! [Int:Any?])[2]! as! [Int:Any?])[1]! as! [Int:Any?])[0])

//Now we have to DOUBLE UNWRAP the final value (because, remember, getGift returns an optional) AND force cast it to the type we hope it is

let asdf : String = b4r!! as! String

print(asdf)

扫码关注云+社区