猿问

在斯威夫特语中,感叹号是什么意思?

在斯威夫特语中,感叹号是什么意思?

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

我对斯威夫特语很陌生。只是想把基本的东西弄下来。


最新情况:
我漏掉的谜题(在答案中没有直接说明-至少在写这篇文章的时候没有)-就是当你做以下事情时:

var john: Person?

这并不意味着“john是类型的Person“可能是零”,正如我最初所想的,我只是误解了这一点。PersonPerson?是完全不同的类型。一旦我抓住了这个,所有的人?!疯狂,以及下面这些伟大的答案,更有意义。


慕丝7291255
浏览 629回答 3
3回答

慕桂英3389331

“打开实例”意味着什么?为什么有这个必要?就我所能做的(这对我来说也是很新的).“包装”一词意味着我们应该把一个可选的变量当作礼物,包在闪亮的纸里,这可能(可悲的!)空空如也.当“包装”时,可选变量的值是带有两个可能值的枚举(有点像布尔值)。此枚举描述变量是否持有值(Some(T)),或不(None).如果存在值,则可以通过“解包装”变量(获取T从…Some(T)).你还好吗john!.apartment = number73不同于john.apartment = number73?(释义)如果您写入可选变量的名称(如文本)john,没有!),这指的是“包装”枚举(/None),而不是值本身(T)。所以john不是Person,而且它没有一个apartment成员:john.apartment // 'Person?' does not have a member named 'apartment'实际Person可以各种方式展开值:“强制拆开”:john!(给出Person如果存在,则为值,如果为零,则为运行时错误)“任择约束力”:if let p = john { println(p) }(执行println(如果存在该值)“可选链接”:john?.learnAboutSwift()(如果值存在,则执行此组合方法)我猜您选择了其中一种方式来展开包装,这取决于在零情况下应该发生什么,以及这种情况发生的可能性有多大。这种语言设计强制显式地处理零情况,我认为这比Obj-C(这里很容易忘记处理零情况)提高了安全性。更新:感叹号也用于声明“隐式解包装选项”的语法中。在到目前为止的示例中,john变量已声明为var john:Person?,这是可选的。如果您想要该变量的实际值,则必须使用上述三种方法之一展开它。如果它被宣布为var john:Person!相反,变量将是一个隐式未包装的可选项(请参阅Apple书中带有此标题的部分)。在访问值时不需要打开此类变量,并且john可以在不使用其他语法的情况下使用。但苹果的书上说:当变量可能在以后变为零时,不应使用隐式展开选项。如果需要在变量的生存期内检查零值,请始终使用普通可选类型。更新2:文章“有趣的斯威夫特特征“MikeAsh给出了一些选择类型的动机,我认为这是伟大的,清晰的写作。”更新3:另一篇关于隐式解包可选使用感叹号:“斯威夫特与最后一英里这篇文章解释说,这是苹果公司的一项实用措施,用于声明它们的目标-C框架所使用的类型,其中可能包含零。声明类型为可选类型(使用?)或隐式展开(使用!)是“安全和方便之间的权衡”。在本文中给出的示例中,Apple选择将这些类型声明为隐式解包装,从而使调用代码更方便,但安全性更低。也许苹果将来可能会梳理它们的框架,根据目标C代码的准确行为,消除隐式展开(“可能永远不会为零”)参数的不确定性,并将其替换为可选(“当然可以是零,特别是[希望,文档!]环境”)或标准的非可选声明(“从不为零”)。

繁华开满天机

我认为不同之处在于:var john: Person?意味着约翰可以是零john?.apartment = number73编译器将这一行解释为:if john != nil {     john.apartment = number73 }当john!.apartment = number73编译器将这一行简单地解释为:john.apartment = number73因此,使用!将打开if语句,使其运行得更快,但如果John为0,则会发生运行时错误。所以这里的包装并不意味着它是内存包装的,但它意味着它是被代码包装的,在本例中它是用if语句包装的,而且由于Apple非常关注运行时的性能,所以他们希望给您一种方法,使您的应用程序能够以最好的性能运行。最新情况:四年后回到这个答案,因为我在Stackoverlow中获得了最高的声誉:)当时我有点误解了展开的意义。现在,4年后,我相信在这里展开的意义是扩展代码,从它原来的紧凑形式。同时,它也意味着消除对象周围的模糊性,因为我们不能确定它的定义是否为零。就像上面艾希礼的回答一样,把它当作一件礼物,里面什么也不包含。但我仍然认为展开是代码展开,而不是使用枚举时基于内存的展开。
随时随地看视频慕课网APP
我要回答