【问题标题】:When to use ?, !, None, or Lazy?何时使用 ?、!、None 或 Lazy?
【发布时间】:2015-06-28 07:24:39
【问题描述】:

我刚开始学习 Swift,最近发现了

  1. “普通”变量(因为没有更好的名称):

    例如:var test1: String

  2. “可选”变量

    例如:var test2: String?

  3. “隐式展开的可选”

    例如:var test3: String!

  4. 惰性变量

    例如:lazy var test4: String

我的理解是这样的:

  1. 使用“可选”变量 (?) 当变量可能会或可能不会在未来从初始化开始的某个时间点进行初始化时

  2. 在保证初始化变量时使用“隐式解包选项” (!)

  3. 选项可以通过“强制展开”

    转换为隐式展开的选项

    例如:let possibleString: String? = "Hello" println(possibleString!)

  4. 在初始化之前不需要设置某些东西时使用“惰性变量”(似乎这些可以与 (?) 或 (!) 一起使用)

因此,我的问题是:

  1. 何时使用选项 1 - 不带 的变量?并且没有!

  2. 什么时候使用“懒惰”

  3. 我读到“懒惰”经常用于singletons - 为什么?

我在 Java 和 C++ 术语方面拥有最丰富的经验,如果这有助于我的回答背景。

编辑:这是我发现的所有内容(主要问题是 "Normal""Implicitly Unwrapped Optionals"

  1. “普通”变量必须初始化:(a)在同一行,(b)在使用前(使用是指对对象的某些操作)在同一范围内,(c)在init iff 变量是一个字段。 注意:init 的范围是类范围内的所有内容,而不是类内函数范围内的所有内容。
  2. 打印隐式展开的可选选项将打印“nil”,但使用变量的函数会引发运行时异常。同时,使用(包括打印)Normal 变量根本不允许程序编译
  3. 使用目的! over "" (Nothing) 是 (a) 更宽松,因为程序将编译(并在变量实际初始化的情况下正确运行)和 (b) 让您不在一开始就初始化所有内容。 注意:如果是Normal变量,任何字段未声明都是编译时错误。

【问题讨论】:

    标签: ios iphone swift variables optional


    【解决方案1】:

    不完全是。

    所有变量必须在第一次使用前初始化,所有类/结构存储的属性必须在各自的初始化器中赋值。可选项不是在某些时候允许未初始化,而是允许不包含任何值,由nil 表示,它仍然是此类变量的完美初始化声明。因此,如果在初始化时无法知道某些内容,那么您可能会在其中使用某种可选的(例如,委托代表视图)。

    隐式展开的可选项是变量可能为空的情况的一种简写,但我们绝对确定当我们真正使用它时,它会保存一个实际值(典型示例是视图控制器中的一个属性持有对视图的引用)。

    强制解包不会将可选项转换为隐式解包的可选项,相反,它会为您提供一个如果存在则存在的值(即,如果可选项不是nil),如果不存在则抛出异常。

    当您希望将它们的初始化推迟到稍后阶段,即该属性实际上是第一次使用时,可以使用惰性属性。通常的情况是,如果您需要访问昂贵的资源来执行此操作(从磁盘加载大文件,通过网络下载等),特别是如果可能存在根本不使用此类属性的情况(为什么加载如果我们可能不使用它,它从磁盘中获取?)。

    【讨论】:

    • 啊,好吧,我什么时候使用 var test1: String //with no ?和不 ! ?
    • 你会写几千行 Swift 代码,并最终弄明白。
    • @AeonNeo,这取决于您的设计。如果属性“无价值”是流程的一部分,则使用“?”。如果它几乎总是有一个值,除了一些“特殊”时期,它不会,但在这些时期不会被访问,请使用“!”。否则坚持“正常”属性。一般来说,如果您可以不使用可选选项,请不要使用它们。这些有时会相当棘手(尤其是隐式展开的)。
    【解决方案2】:

    让我们看看苹果的例子

    class Person {
        var residence: Residence?
    }
    
    class Residence {
        var numberOfRooms = 1
    }
    

    Residence 实例有一个名为 numberOfRooms 的 Int 属性,默认值为 1。Person 实例有一个可选的 Residence 类型 Residence? 属性。

    如果你创建一个新的 Person 实例,它的居住属性默认初始化为 nil,因为它是可选的。

    1.如果您需要将属性默认值设为nil - 使用可选。使用不带 ? 的变量和 ! - 像'numberOfRooms' -

    您可以在初始化程序中设置存储属性的初始值,如上所示。或者,将默认属性值指定为属性声明的一部分。您可以通过在定义属性时为其分配初始值来指定默认属性值。

    注意

    如果属性始终采用相同的初始值,请提供默认值 值而不是在初始化程序中设置值。结束 结果相同,但默认值与属性的 初始化更接近其声明。它使时间更短, 更清晰的初始化器并使您能够推断属性的类型 从它的默认值。默认值也让你更容易 利用默认初始化器和初始化器继承。

    2. !用于访问包装在变量中的值,当它不是零时,否则抛出异常。所以,你可以使用!为了给你类的用户做标记 - '在你打开它的时候这个值不会是 nil'

    3. 使用惰性变量当您想稍后初始化它时,不是在整个对象创建时,而是在您向 getter 请求数据时。这在属性存储数组时很有用,例如:

    lazy var players: [String] = {
            var temporaryPlayers = [String]()
            temporaryPlayers.append("John Doe")
            return temporaryPlayers
            }()
    

    什么时候应该使用延迟初始化?

    何时使用延迟初始化的一个例子是,直到对象初始化后才知道属性的初始值。

    【讨论】:

    • 当我有这个代码时: class Car{ var Passengers: Int init(){ //passengers = 1 } } 这不会编译,因为它说不是所有的东西都被初始化了,这不是说但它没有输入默认值?
    • 同意,我会编辑答案。我看了documentaion,你必须在没有使用时初始化var?和!
    • @Doro 啊,好吧。在这种情况下,不要!和不使用任何东西最后基本上有相同的功能?
    • 是的,lazy 主要实现的是模式,而不是值存储的概念。
    • lazy (lazy var a: String) 和 have (var a: String) 一样吗?
    【解决方案3】:

    简短说明:

    非可选变量始终有一个值,并且永远不能为零。 变量必须在 init 方法或声明行中初始化。

    var a : String
    var b = "bar"
    
    init {
        a = "foo"
    }
    

    隐式展开的可选变量必须在 init 方法中初始化 或在声明行中,但保证在使用时始终具有值

    var a : String!
    
    func viewDidLoad() {
        a = "Hello"
        a += " world!"
    }
    

    可选变量可能有一个值并且在声明时为零

    var a : String?  // = nil
    

    惰性变量稍后在第一次使用时初始化

    class foo {
      lazy var bar : String = {
        return "Hello"
        }()
    }
    

    【讨论】:

    • 在这种情况下,使用 var a: String 与 var a: String 相比有什么好处(如果有的话)!鉴于两者都必须在 init 方法/声明行/相同范围内初始化?
    • var a: String! 不得在 init 方法/声明行中初始化。我更改了帖子以澄清
    • 嗯,我可以编译/运行:var a: String! = "this is a string",所以可以初始化
    • 它可以,但不像非可选的那样不是必需的
    猜你喜欢
    • 2017-07-14
    • 2015-03-05
    • 1970-01-01
    • 1970-01-01
    • 2011-10-14
    • 1970-01-01
    • 2013-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多