【问题标题】:Implicitly unwrapped optional made immutable隐式展开的可选项使其不可变
【发布时间】:2014-06-06 22:48:30
【问题描述】:

为什么我不能改变隐式展开的可选变量?

这是一个重现问题的简短示例:

带数组

var list: [Int]! = [1]
list.append(10) // Error here

Immutable value of type '[Int]' only has mutating members named 'append'

Int

var number: Int! = 1
number = 2
number = 2 + number
number += 2 // Error here

Could not find an overload for '+=' that accepts the supplied arguments

【问题讨论】:

    标签: swift


    【解决方案1】:

    因为您尝试改变它们的方式是改变值(它们是不可变的)而不是改变var。

    在 Swift 中,值类型是不可变的。始终如一。

    变异不是值的变异,而是包含值的变量的变异。

    在Int 的情况下,+= 运算符在左侧获取结构,在右侧获取 Int,它无法将结构添加到 int。

    在Array 的情况下,append 是一个变异成员。但它是在不直接存储在变量中的不可变值上调用的。它只能对直接存储在变量中的值进行操作(这就是使它们可变的原因:它们存储在变量中的事实。它们并不是真正可变的,变量是)。

    【讨论】:

    • 错了。在 Swift 中,像 String 这样的值类型和像 Int[] 这样的集合类型是在分配给变量时默认是可变的。只有当您将它们分配给常量(即let)时,它们才会变得不可变。请refer 到documentation。
    • 可变的是变量,而不是值。对于值类型,值始终是不可变的。文档有时以非正式的方式说话,有时则更正式。当它说字符串或数组在分配给var 时是可变的,而在分配给let 时是不可变的,这只是说值本身是不可变的,但是您可以将它分配给可变的var 并进行变异变种。这就是为什么你不能调用任何只是另一种类型的构造函数的参数的变异方法。
    • "If you create an array or a dictionary and assign it to a variable, the collection that is created will be mutable." 我不明白这是怎么回事。
    • 不清楚。它只是不意味着你认为它意味着什么。这意味着您可以调用该值的变异方法。变异方法所做的是他们接受一个隐藏参数,即变量的地址,创建一个新值,并将其分配给变量。它们不会改变实际的原始值(除非编译器可以证明没有别名或共享,在这种情况下它可以执行优化并实际改变原始存储,但这会透明地发生)。
    • 特别注意,对于数组,数组的突变意味着长度的突变,而不是内容的突变。事实上,这就是为什么 append 调用在 OP 中失败的原因:它是数组的一种变异方法。它需要创建一个新数组并将其分配给一个变量,但它只有在它有一个变量的情况下才能这样做,并且没有包含该数组的变量。
    【解决方案2】:

    更新:

    这已在 Xcode Beta 5 中得到修复,但有一个小警告:

    var list: [Int]! = [1]
    list.append(10)
    
    var number: Int! = 1
    number! += 2
    number += 2 // compile error
    

    数组按预期工作,但似乎现在整数仍然需要显式展开才能允许使用+=


    目前,这只是 Optionals 的本质(无论是否隐式展开)。 unwrap 运算符返回一个不可变的值。 This is likely to be fixed or a better solution will be provided in the future.

    目前唯一的解决方法是将数组包装在一个类中:

    class IntArray {
        var elements : [Int]
    }
    

    【讨论】:

    • 解包操作符返回一个不可变的值,因为这是不可变操作的本质。正如拉特纳所说,没有明显的解决方案。使 unwrap 操作可变不是解决方案:您将无法在不可变 Optional 上使用它,并且它不会解决问题,因为返回的值仍然是不可变的(因为所有值类型始终是不可变的)。
    猜你喜欢
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多