为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕丝7291255 2019-06-23 15:26:44
在斯威夫特语中,感叹号是什么意思?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“可能是零”,正如我最初所想的,我只是误解了这一点。Person和Person?是完全不同的类型。一旦我抓住了这个,所有的人?, !疯狂,以及下面这些伟大的答案,更有意义。
查看完整描述

3 回答

?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

“打开实例”意味着什么?为什么有这个必要?

就我所能做的(这对我来说也是很新的).

“包装”一词意味着我们应该把一个可选的变量当作礼物,包在闪亮的纸里,这可能(可悲的!)空空如也.

当“包装”时,可选变量的值是带有两个可能值的枚举(有点像布尔值)。此枚举描述变量是否持有值(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代码的准确行为,消除隐式展开(“可能永远不会为零”)参数的不确定性,并将其替换为可选(“当然可以是零,特别是[希望,文档!]环境”)或标准的非可选声明(“从不为零”)。


查看完整回答
反对 回复 2019-06-23
?
繁华开满天机

TA贡献1816条经验 获得超4个赞

我认为不同之处在于:

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年后,我相信在这里展开的意义是扩展代码,从它原来的紧凑形式。同时,它也意味着消除对象周围的模糊性,因为我们不能确定它的定义是否为零。就像上面艾希礼的回答一样,把它当作一件礼物,里面什么也不包含。但我仍然认为展开是代码展开,而不是使用枚举时基于内存的展开。


查看完整回答
反对 回复 2019-06-23
  • 3 回答
  • 0 关注
  • 628 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信