【问题标题】:Getting around let arguments in Swift在 Swift 中绕过 let 参数
【发布时间】:2016-10-07 16:02:03
【问题描述】:

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

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")
}

具有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 中已弃用。相同的单行解决方法在那里工作。有没有更好的更惯用的方法来做到这一点?最初的开始只是将一些常见的行为提取到协议扩展中,而不是继承树。感觉就像我为这个选择付出了代价。

【问题讨论】:

    标签: swift var let


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 我不知道协议声明的 class 修饰符。这对您有帮助,谢谢!
    猜你喜欢
    • 1970-01-01
    • 2014-08-17
    • 1970-01-01
    • 1970-01-01
    • 2021-05-02
    • 2016-12-10
    • 2015-09-20
    • 2011-09-01
    • 2018-10-18
    相关资源
    最近更新 更多