当前位置: 首页 > 面试题库 >

“后卫让foo = foo”何时合法?

滕学义
2023-03-14
问题内容

早在2016年11月,我发布了一个问题,询问为什么我不能使用Guard创建与变量名称相同的未包装版本的变量,就像让let那样:

链接: 为什么后卫不让foo = foo有效?

当我编写该问题时,以下代码将无法编译,并显示“定义与先前值冲突”的错误:

//Test of using guard to create an unwrapped version of a var, like if let
func guardTest(_ viewController: UIViewController?) -> UIViewController? {
  // Check if the current viewController exists
  print(String(describing: viewController))
  guard let viewController = viewController else {
    return nil
  }
  print(String(describing: viewController))

  return viewController
}

但是,我只是在工作中发现了一些可以做到这一点的代码,现在它可以毫无抱怨地进行编译,并且可以完成我想要的工作!运行时,print语句显示foo在警卫之前是可选的,而在包装后是未包装的可选的:

viewController = Optional(<TrochoidDemo.ViewController: 0x7ff16a039a00>)
viewController = <TrochoidDemo.ViewController: 0x7ff16a039a00>

guardTest(_:)如果您想尝试一下,我将测试功能添加到了最新的开源项目中。可以在Github上的
https://github.com/DuncanMC/TrochoidDemo上找到该功能


我很高兴这个构造现在可以按我希望的方式工作,但是对于 为什么 现在合法以及更改发生的时间感到困惑。

是否有人知道对语言定义的最新更改,使此构造在以前从未有过的地方起作用?


问题答案:

TL; DR

guard let foo = foo如果foo在其他范围内定义,则为合法。

您的链接问题中的示例:

func test()
{
  let a: Int? = 1

  guard let a = a else{
    return
  }
  print("a = \(a)")
}

仍然不起作用,因为该guard语句试图a在相同范围内创建另一个变量。

这个例子:

//Test of using guard to create an unwrapped version of a var, like if let
func guardTest(_ viewController: UIViewController?) -> UIViewController? {
  // Check if the current viewController exists
  print(String(describing: viewController))
  guard let viewController = viewController else {
    return nil
  }
  print(String(describing: viewController))

  return viewController
}

可以这样做的原因相同:

func test(a: Int)
{
    print(type(of: a))  // Int

    let a = 3.14

    print(type(of: a))  // Double
}

该函数的参数在不同的范围内定义,因此Swift允许您创建具有相同名称的局部变量。



 类似资料:
  • 问题内容: 在Swift中,您可以使用if let可选绑定将可选内容解包为具有相同名称的常量或变量: 对于语句中的所有内容,可选项都被包装为常规int。 同样,我可以使用保护语句来达到类似的效果 但是,我不能使用这样的代码: 为什么不? 在保护语句中,如果保护语句的条件失败,则执行else子句,然后退出当前作用域。如果条件成功,则将从保护语句的右括号到当前作用域的结尾创建一个新的变量/常量。 为什

  • 问题内容: 在Java中,这两个函数声明之间有什么区别? 在这里,您可以找到该问题的答案,但仅适用于 C / C ++ 。在这些语言中,两种声明样式的存在是完全有意义的。 但是在 Java 中这有什么意义呢? 问题答案: 后者在Java中是非法的。您不能声明这样的方法。您应该得到这样的错误: 因此,不仅没有意义-您根本找不到尝试使用此样式的有效代码。

  • 问题内容: Foo具有: 和酒吧有: 除了表被称为foo_bar还是bar_foo之外,mappedBy属性的位置对双向关系有何影响?没有mapByBy属性,我得到两个联接表,即foo_bar和bar_foo。 问题答案: 该文档说: 如果关联是双向的,则一侧必须是所有者,而一侧必须是反向端(即,在更新关联表中的关系值时,它将被忽略): 因此,具有属性的一面是反面。没有属性的一方是所有者。 所有者

  • foo-display-lyrics 是 Foobar 2000 播放器用来显示歌词的插件。

  • 问题内容: 我看到其他地方说: 等于 我测试了一下,他们确实做了同样的事情。但为什么?到底是什么? 问题答案: AND和OR运算符都可以捷径。 因此,仅在第一个表达式为true时才尝试第二个表达式(更确切地说,是类似事实的表达式)。第二个操作确实起作用(无论其内容如何)的事实无关紧要,因为除非第一个表达式的计算结果为真,否则它不会执行。如果是事实,则将执行它以尝试第二次测试。 相反,如果语句中的第

  • 问题内容: 请考虑以下两个函数定义: 两者之间有什么区别吗?如果没有,那为什么会有void争论呢?审美原因? 问题答案: 在C中: 表示“带有未指定类型的未指定数量的参数的函数” 表示不带参数的函数” 在C ++中: 表示“foo不带参数的函数” 表示“foo不带参数的函数” 因此,通过编写,我们可以在两种语言中实现相同的解释,并使标头变为多语言(尽管我们通常需要对标头做更多的事情才能使它们真正成