微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在便利初始值设定项中使用 `self =` 委托给 JSONDecoder 或 Swift 中的工厂方法,以避免 `Cannot assign to value: 'self' is immutable`

如何解决在便利初始值设定项中使用 `self =` 委托给 JSONDecoder 或 Swift 中的工厂方法,以避免 `Cannot assign to value: 'self' is immutable`

有时在 Swift 中,为委托给 JSONDecoder 或工厂方法的类编写初始化程序可能会很方便。例如,一个人可能想写

final class Test: Codable {
    let foo: Int
    
    init(foo: Int) {
        self.foo = foo
    }
    
    func jsonData() throws -> Data {
        try JSONEncoder().encode(self)
    }
    
    convenience init(fromJSON data: Data) throws {
        self = try JSONDecoder().decode(Self.self,from: data)
    }
}

let test = Test(foo: 42)
let data = try test.jsonData()
let decodedTest = try Test(fromJSON: data)
print(decodedTest.foo)

但这无法编译

Cannot assign to value: 'self' is immutable.

解决此问题的解决方案是什么?

解决方法

首先,请注意此限制仅存在于 class 中,因此示例初始化程序将按原样适用于 structenum,但并非所有情况都允许更改class 到这些类型之一。

这种对 class 初始化器的限制是一个经常出现在这个网站 (for example) 上的痛点。在 Swift 论坛上有一个 thread 讨论这个问题,并且已经开始添加必要的语言特性来编译上面的示例代码,但是这在 Swift 5.4 中还不完整。 来自线程:

Swift 自己的标准库和 Foundation 覆盖层通过使类符合虚拟协议并在必要时使用协议扩展初始化程序来解决此缺失的功能。

使用这个想法来修复示例代码收益

final class Test: Codable {
    let foo: Int
    
    init(foo: Int) {
        self.foo = foo
    }
    
    func jsonData() throws -> Data {
        try JSONEncoder().encode(self)
    }
}

protocol TestProtocol: Decodable {}
extension Test: TestProtocol {}
extension TestProtocol {
    init(fromJSON data: Data) throws {
        self = try JSONDecoder().decode(Self.self,from: data)
    }
}

let test = Test(foo: 42)
let data = try test.jsonData()
let decodedTest = try Test(fromJSON: data)
print(decodedTest.foo)

效果很好。如果 Test 是唯一符合 TestProtocol 的类型,那么只有 Test 会得到这个初始化器。

另一种方法是简单地扩展 Decodable 或您的类符合的其他协议,但如果您不希望符合该协议的其他类型也获得您的初始值设定项,这可能是不可取的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?