Swift:在协议一致性中覆盖协议扩展的关联类型

时间:2018-02-14 16:03:33

标签: ios swift protocols

所以,我正在努力实现这个目标:

拥有一个带有相关类型的协议,该协议将处理json解析到他的扩展中。关联类型必须符合Decodable

protocol MyProtocol {
  associatedtype ResponseType: Decodable
  func handleResponse(data: Data) -> ResponseType
}

我想要做的是将responseType的默认类型设置为我的扩展,然后,如果需要,将该类型覆盖到类或结构一致性中。这样的事情。

extension MyProtocol {
  typealias ResponseType = MyDefaultDecodableType

  func handleResponse(data: Data) -> ResponseType { ... }
}

class MyObject: MyProtocol {
  typealias ResponseType = AnotherDecodableType
}

问题是我在MyObject内发现了这样的错误:

error: type 'MyObject' does not conform to protocol 'MyProtocol'
class MyObject: MyProtocol {
      ^
note: multiple matching types named 'ResponseType'
    associatedtype ResponseType: Decodable
                   ^
note: possibly intended match
  typealias ResponseType = AnotherDecodableType
            ^
note: possibly intended match
    public typealias ResponseType = MyDefaultDecodableType

我不知道是否有可能实现我正在尝试的东西或者我正在接近错误的方式。任何人都可以给我一些亮点吗?

感谢。

1 个答案:

答案 0 :(得分:0)

我创建了相同的代码。这里有一些事实需要理解。

extension MyProtocol {
    typealias ResponseType = MyDefaultDecodableType

    func handleResponse(data: Data) -> ResponseType {

        return try! JSONDecoder().decode(MyDefaultDecodableType.self, from: data)

    }
}

从概念上讲,Swift中没有通用协议。但是通过使用typealias,我们可以为另一种类型声明一个必需的别名。

您的扩展程序不需要定义typealias ResponseType = MyDefaultDecodableType,因为它将使用MyDefaultDecodableType提供一些默认实现,因此它没用。

所以你的扩展将是这样的

extension MyProtocol {
  //  typealias ResponseType = MyDefaultDecodableType // NO NEED FOR IT

    func handleResponse(data: Data) -> MyDefaultDecodableType {
        print("Test \(self)")
        return try! JSONDecoder().decode(MyDefaultDecodableType.self, from: data)

    }
}

现在你可以定义

class MyObject:MyProtocol {
    typealias ResponseType = AnotherDecodableType

    func handleResponse(data: Data) -> ResponseType {
        print("Test \(self)")

        return try! JSONDecoder().decode(AnotherDecodableType.self, from: data)

    }

}
class MyObject2:MyProtocol {


}

没有任何错误

现在,如果您使用

MyObject().handleResponse(data:data)
MyObject2().handleResponse(data:data2)

你会得到

  

测试__lldb_expr_44.MyObject

     

测试__lldb_expr_44.MyObject2