在 Swift 中绕过 let 参数

Getting around let arguments in Swift

这是一个简单的游乐场示例:

class Foobar {
    var name = ""

    init(name:String) {
        self.name = name
    }

    func modifyName(modification:String) {
        self.name += modification
    }
}

let list = [Foobar(name:"I"), Foobar(name:"Me"), Foobar(name:"Myself")]

for each in list {
    each.modifyName(" rules")
}

一个 class 和 name 变量,以及一个可以修改该变量的函数。列一个表,现在用一个for in来练习修改功能

但是。如果我将 modifyName 变量重构为协议扩展:

class Foobar {
    var name = ""

    init(name:String) {
        self.name = name
    }
}

protocol Modifiable {
    var name:String { get set }
}

extension Modifiable {
    mutating func modifyName(modification:String) {
        self.name += modification
    }
}

extension Foobar:Modifiable { }

然后 for in 将不再起作用,因为 Modifiable 扩展需要将 modifyName 注释为 mutating。发出的错误是 error: cannot use mutating member on immutable value: 'each' is a 'let' constant。有一个简单的解决方法,但感觉我在滥用某些东西:

for each in list {
    var each = each
    each.modifyName(" rules")
}

我遇到过同样的问题,函数的参数已被注释标记。过去,您可以在 arg 列表中用 var 标记这些参数,但在最新版本的 swift 中已弃用。同样的单行解决方法在那里工作。有没有更好更惯用的方法来做到这一点?最初开始这个,只是将一些常见的行为提取到协议扩展中,而不是继承树。感觉就像我在为那个选择付出代价。

,您的单行解决方法不一定有效。您的协议不要求符合类型是引用类型 (类)。如果一个结构符合你的协议,并且在数组中,var each = each 会制作一个 copy,修改副本不会修改数组中的值。

您可以要求您的对象是 类、protocol Modifiable: class,在这种情况下我相信 mutating 将不再被允许(或者,至少您的代码将正常工作) .

但假设你想保留 mutating,你可以这样做来修改原地的元素:

for i in list.indices {
    list[i].modifyName()
}

当然,你的数组也必须是var,因为它也是一个结构value semantics