不可变值仅具有可变成员

16

我使用var声明了一个数组,并在init()中填充了它。然而,当我尝试改变这个数组时,我得到了很多错误,告诉我这个数组是不可变的。我错过了什么?

struct Deck {
    var cards: Card[] = []

    init () {
        for i in 1...4 {
            for ii in 1...13 {
                self.cards.append(Card(rank: Rank.fromRaw(ii)!, suit: Suit.fromRaw(i)!))
            }
        }
    }

    func shuffle () {
        var shuffledDeck: Card[] = []
        var count = self.cards.count

        for i in 1...52 {
            var limit = count - i
            var key = Int(arc4random_uniform(UInt32(limit)));
            shuffledDeck.append(self.cards[key])
            self.cards.removeAtIndex(key)
        }

        self.cards = shuffledDeck
    }
}

我遇到的错误:

Playground execution failed: error:
<REPL>:75:22: error: immutable value of type 'Card[]' only has mutating members named 'removeAtIndex'
            self.cards.removeAtIndex(key)
                 ^     ~~~~~~~~~~~~~
<REPL>:78:24: error: cannot assign to 'cards' in 'self'
            self.cards = shuffledDeck
1个回答

27
一个struct结构体被认为是一个值类型,所以默认情况下它是不可变的。如果你想使用一个方法来改变它,你必须声明这个方法是mutating的。引用Swift书中的话:结构体和枚举是值类型。默认情况下,值类型的属性不能从实例方法内部修改。但是,如果你需要在特定方法内修改结构体或枚举的属性,你可以选择对该方法进行变异行为。该方法可以从内部改变(即更改)其属性,并在方法结束时将其所做的任何更改写回原始结构。该方法还可以将全新的实例分配给它的隐式self属性,在方法结束时,这个新实例将替换现有的实例。你可以通过在该方法的func关键字之前放置mutating关键字来选择这种行为。

3
太棒了,谢谢!这样做就可以了。不过我必须将 let deck = Deck() 改为 var deck = Deck() 才能使其工作。 - Guido Bouman
1
这是因为你使用 let deck = Deck() 定义了一个不可变的 Deck,而你又试图在 shuffle 函数中对其进行改变。如果你想要做这种操作,我想知道将你的结构体改为类是否会是更好的方法。 - Mac_Cain13
使用一个类对于这个想法肯定是更好的方法。 - Guido Bouman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接