Swift 语言中的感叹号是什么意思?

2023-12-09

Swift 编程语言指南有以下示例:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
    deinit { println("\(name) is being deinitialized") }
}

class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    var tenant: Person?
    deinit { println("Apartment #\(number) is being deinitialized") }
}

var john: Person?
var number73: Apartment?

john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)

//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)

然后,当将公寓分配给该人时,他们使用感叹号来“打开实例”:

john!.apartment = number73

“打开实例”是什么意思?为什么有必要?它与仅执行以下操作有何不同:

john.apartment = number73

我对 Swift 语言非常陌生。只是想了解基础知识。


UPDATE:
我所遗漏的一大难题(在答案中没有直接说明 - 至少在撰写本文时没有)是当您执行以下操作时:

var john: Person?

这并不意味着“john属于类型Person正如我最初所想的那样,它可能为零”。我只是误解了Person and Person?是完全独立的类型。一旦我明白了这一点,其他的一切?, !疯狂,以及下面的精彩答案,更有意义。


“打开实例”是什么意思?为什么有必要?

据我所知(这对我来说也是很新的)......

“包裹”一词意味着我们应该将可选变量视为礼物,包裹在闪亮的纸中,它可能(遗憾的是!)是空的.

当“包装”时,可选变量的值是一个具有两个可能值的枚举(有点像布尔值)。该枚举描述了变量是否拥有一个值(Some(T)), 或不 (None).

如果有一个值,则可以通过“展开”变量来获得该值(获取T from Some(T)).

How is john!.apartment = number73不同于john.apartment = number73? (转述)

如果您编写可选变量的名称(例如文本john,没有!),这是指“包装”枚举(Some/None),而不是值本身(T)。所以john不是一个实例Person,并且它没有apartment member:

john.apartment
// 'Person?' does not have a member named 'apartment'

实际上Person值可以通过多种方式展开:

  • “强制展开”:john!(给出Person值(如果存在),如果为 nil,则运行时错误)
  • “可选绑定”:if let p = john { println(p) }(执行println如果该值存在)
  • “可选链”:john?.learnAboutSwift()(如果该值存在则执行这个虚构的方法)

我猜你会选择其中一种解包方式,具体取决于零情况下会发生什么以及发生的可能性有多大。这种语言设计强制显式处理 nil 情况,我认为这比 Obj-C 提高了安全性(在 Obj-C 中很容易忘记处理 nil 情况)。

Update:

感叹号也用在声明“隐式解包可选”的语法中。

在到目前为止的示例中,john变量已声明为var john:Person?,并且它是一个可选的。如果您想要该变量的实际值,则必须使用上述三种方法之一将其解包。

如果它被声明为var john:Person!相反,该变量将是隐式解包可选(请参阅 Apple 书中带有此标题的部分)。访问值时无需解开此类变量,并且john无需额外语法即可使用。但苹果公司的书中说:

当变量稍后有可能变为 nil 时,不应使用隐式展开的选项。如果需要在变量的生命周期内检查 nil 值,请始终使用普通的可选类型。

Update 2:

文章《有趣的 Swift 功能迈克·阿什 (Mike Ash) 的文章为可选类型提供了一些动力。我认为这是很棒、清晰的写作。

Update 3:

另一篇关于的有用文章隐式解包可选用于感叹号:“斯威夫特和最后一英里” 作者:Chris Adamson。文章解释说,这是 Apple 的一项实用措施,用于声明其 Objective-C 框架使用的类型,其中可能包含 nil。将类型声明为可选(使用?)或隐式展开(使用!)是“安全性和便利性之间的权衡”。在本文给出的示例中,Apple 选择将类型声明为隐式解包,使调用代码更方便,但安全性较差。

也许苹果将来可能会梳理他们的框架,消除隐式解包(“可能永远不会为零”)参数的不确定性,并将它们替换为可选(“在特定情况下当然可能为零”)或标准非- 可选(“永远不会为零”)声明,基于 Objective-C 代码的确切行为。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift 语言中的感叹号是什么意思? 的相关文章

随机推荐