为什么guard let self = self else { return } 可以编译成功

问题描述 投票:0回答:2

问题1:

guard let self = self else { return }
中,第一个
self
和第二个
self
是一样的,为什么可以编译成功?因为正常的
let self = self
会编译出错。

问题2:即使我在某些项目中发现

guard let self else { return }
,为什么还能编译成功?

ios swift closures guard
2个回答
0
投票

一些链接供您参考:

  1. SE-0079讨论了

    if let self = self {…}
    模式的使用:

    所提出的解决方案需要允许使用可选绑定将 self 从弱引用升级到强引用。

    该提案取代了语法:

    if let strongSelf = self { … }
    

    使用一些避免引入单独变量名称的混乱的东西,将其减少为:

    if let self = self { … }`
    
  2. SE-0345中考虑了此语法的缩短,其中表示:

    使用

    if let foo = foo { ... }
    进行可选绑定,创建一个隐藏现有可选变量的未包装变量,是一种极其常见的模式。此模式要求作者重复引用的标识符两次,这可能会导致这些可选绑定条件变得冗长,尤其是在使用冗长的变量名称时。当隐藏现有变量时,我们应该引入可选绑定的简写语法:

    let foo: Foo? = ...
    
    if let foo {
        // `foo` is of type `Foo`
    }
    

    该模式也适用于自我,因此我第一点中的示例简化为:

    if let self { … }`
    
  3. FWIW,SE-0365,在“内隐自我”的讨论中,展示了许多

    guard
    模式的示例:

    guard let self else {…}`
    

0
投票

通过编写

let self = self
,您可以声明一个变量
self
并为其赋予值
self
(即,对该行在内部调用的对象实例的引用)。

Swift 允许变量遮蔽,因此创建一个局部变量

self
来遮蔽外部作用域中的标识符
self
是合法的。

但有一个警告:

self
在 Swift 中也是一个特殊的词,不能用作变量名(编译器会发出错误“关键字'self'不能在此处用作标识符”)...除非你应用转义技术:让 `self` = self.

另一方面,

guard
不需要这种转义。我想,由于习惯用法
guard let self = self
如此常见,语言开发人员决定破例,以避免一些样板代码。

在该语言的更高版本中,他们还引入了用于展开可选值的简写语法:

guard let self
。事实上,您可以将它与任何可选变量一起使用来打开它:
guard let anyOptional

至于为什么

guard let self else { return }
在某些地方无法编译,没有更多细节就很难说,但我有两个假设:

  1. 该项目可能使用早于引入简写语法的语言版本进行编译,因此该语法被视为无效。
  2. self
    本身可能在上下文中不可用(即代码是在对象实例之外编写的,例如在全局范围内)。
© www.soinside.com 2019 - 2024. All rights reserved.