在斯威夫特3:想象一下,你希望你的模型是值类型(结构),通过了您的应用程序。但是你也希望使用Core Data/Realm来持久化这些模型,这需要你创建类。然后,你可以使用JSON(这需要结构和类都支持JSON反序列化和序列化)的结构转换成类,反之亦然。默认初始化器需要不需要可变的特性
岂不是整齐的,如果你没有写反序列化JSON(以及类似的序列化,但我在这里集中在反序列化)在两个地方,但在协议使用放反序列化,即你的结构和类都使用。
使用结构,我们希望我们的JSON模式,具有不可变的领域,因此,所有的性质在为let
常数。但使用实施反序列化的不允许这种AFAIK。
下面的代码示例工程,但它是丑陋的,因为标记代码中的注释所有不必要的要求(UR)。
struct JSON {
let json: [String: Any]
func value<Value>(_ key: String) throws -> Value {
guard let value = json[key] as? Value else { throw NSError() }
return value
}
}
protocol JSONDeserializable {
init(json: JSON) throws
}
protocol UserModel: JSONDeserializable {
var username: String { get set } // Unwanted requirement (UR) #1: property needs "set" so that it can be initialized within protocol
init() // UR2: needs empty init, because of default implementation of `init(json: JSON)` in `extension UserModel`
}
extension UserModel {
init(json: JSON) throws {
self.init() // UR3: Needs to call this otherwise compilation error: `'self' used before chaining to another self.init requirement`
username = try json.value("username")
}
}
struct UserStruct: UserModel {
// UR4: property cannot be `let`, beause of `set` in protocol.
var username: String = "" // UR5: Property have to have default value because of it being a empty init
init() {}
}
final class UserClass: NSObject, UserModel {
// UR6: analogue with UR4
var username: String = "" // UR7: analogue with UR5
}
let json: JSON = JSON(json: ["username": "Sajjon"])
let u1 = try UserStruct(json: json)
let u2 = try UserClass(json: json)
print(u1.username) // prints "Sajjon"
print(u2.username) // prints "Sajjon"
是否有实现这一目标的另一种方式,用不必要的要求更低的量?或零UR的最佳解决方案?
只需在'UserModel'中设置'init(username:String)'而不是'init()'。 – Hamish
感谢您的建议,我更新@Hamish它使代码重复的问题... – Sajjon
使用'struct's的好处是,你可以仅仅依靠在这种情况下,默认按成员初始化器:)所以,你可以只是删除'UserStruct'的初始化程序。 – Hamish