我正在实施一个模型:
ClientSummary
和ClientDetails
ClientDetails
struct具有ClientSummary
struct的所有属性+一些额外属性init(jsonDictionary: [String: Any])
inits
ClientSummary
和ClientDetails
共享代码的大部分内容我想到的最简单的解决方案就是经典继承,但它不适用于值类型。
我正在尝试用协议解决这个问题,但我无法实现那些“共享内容”。我试图将init的共享部分移动到协议扩展但不能真正实现它。有各种各样的错误。
这是测试代码。
protocol Client {
var name: String { get }
var age: Int { get }
var dateOfBirth: Date { get }
init?(jsonDictionary: [String: Any])
}
struct ClientSummary: Client {
let name: String
let age: Int
let dateOfBirth: Date
init?(jsonDictionary: [String: Any]) {
guard let name = jsonDictionary["name"] as? String else {
return nil
}
self.name = name
age = 1
dateOfBirth = Date()
}
}
struct ClientDetails: Client {
let name: String
let age: Int
let dateOfBirth: Date
let visitHistory: [Date: String]?
init?(jsonDictionary: [String: Any]) {
guard let name = jsonDictionary["name"] as? String else {
return nil
}
self.name = name
age = 1
dateOfBirth = Date()
visitHistory = [Date(): "Test"]
}
}
extension Client {
// A lot of helper methods here
var stringDOB: String {
return formatter.string(from: dateOfBirth)
}
}
答案 0 :(得分:4)
继承是错误的工具。说"详细信息IS-A摘要是没有意义的。"详细信息不是摘要的种。离开他们是否分享很多方法的结构性问题,并关注一个人是否是另一种的基本问题。 (有时重命名事物可以做到这一点,但只要他们重新"摘要"和"细节"继承是没有意义的。)
有意义的是说明详细信息HAS-A。构成,而不是继承。所以你结束了类似的事情:
struct ClientDetails {
let summary: ClientSummary
let visitHistory: [Date: String]?
init?(jsonDictionary: [String: Any]) {
guard let summary = ClientSummary(jsonDictionary: jsonDictionary) else {
return nil
}
self.summary = summary
visitHistory = [Date(): "Test"]
}
// You can add these if you need them, or to conform to Client if that's still useful.
var name: String { return summary.name }
var age: Int { return summary.age }
var dateOfBirth: Date { return summary.dateOfBirth }
}
答案 1 :(得分:0)
我经常希望Swift有一种内置的方法来分离出部分init方法。但是,对于元组来说,它可以做得有点笨拙,如下所示:
struct S {
let foo: String
let bar: Int
let baz: Bool
init() {
(self.foo, self.bar, self.baz) = S.sharedSetup()
}
static func sharedSetup() -> (String, Int, Bool) {
...
}
}
在您的情况下,可以将sharedSetup()方法移动到协议扩展,或者方便它的任何地方。