如何使结构符合协议的属性,而该协议的属性符合Swift 4中的另一个协议?

时间:2018-09-12 02:30:47

标签: swift protocols decodable

我打算将Web服务中的一些JSON数据反映到快速结构中。因此,我创建了一个符合可解码协议的协议,并计划创建一些符合该协议的结构。这是我创建的协议:

protocol XFNovelApiResponse: Decodable {

   var data: Decodable {get}
   var error: NovelApiError {get}
}

struct NovelApiError: Decodable {

   let msg: String
   let errorCode: String
}

它已被编译。但是当我开始写我的结构时,我得到了一个错误。结构的代码在这里:

struct XFNovelGetNovelsApiResponse: XFNovelApiResponse {

    let data: NovelsData

    let error: NovelApiError

    struct NovelsData: Decodable {

    }
}

该错误表明类型'XFNovelGetNovelsApiResponse'不符合协议'XFNovelApiResponse'。我知道应该以错误的方式实现“数据”属性。我该如何解决?谢谢。

1 个答案:

答案 0 :(得分:4)

您要描述data可以容纳的类型,而不是实际类型。这意味着它必须是associatedtype

protocol XFNovelApiResponse: Decodable {
    associatedtype DataType: Decodable
    var data: DataType {get}
    var error: NovelApiError {get}
}

请注意,具有关联类型的协议会产生很多复杂性,因此,您应该仔细考虑该协议是否确实必要,或者例如XFNovelApiResponse是否可以泛型。这取决于其他哪些类型可以实现此协议。

例如,没有协议的一组类似数据结构的另一种实现将是:

struct XFNovelApiResponse<DataType: Decodable>: Decodable {
    var data: DataType
    var error: NovelApiError
}

struct NovelsData: Decodable {
}

struct NovelApiError: Decodable {

    let msg: String
    let errorCode: String
}

let novels = XFNovelApiResponse(data: NovelsData(),
                                error: NovelApiError(msg: "", errorCode: ""))

或者,您可以使用允许继承的类和子类来实现此目的。结构不从协议继承,它们符合协议。如果您真的想继承,那么类是正确的工具。 (但是我希望在这里泛型是更好的解决方案。)