简体   繁体   中英

Swift: override associatedtype from protocol extension in protocol conformance

So, I'm trying to achieve this:

Have a protocol with associatedtype who will handle json parsing into his extension. The associatedtype must conform to Decodable :

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

What I'm want to do is to set a default type for responseType into my extension and then, if needed, override that type into the class, or struct conformance. Something like this.

extension MyProtocol {
  typealias ResponseType = MyDefaultDecodableType

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

class MyObject: MyProtocol {
  typealias ResponseType = AnotherDecodableType
}

Problem is I'm getting an error like this inside 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

I don't know if it's possible to achieve what I'm trying or I'm approaching the wrong way. Anyone can give me some light?

Thanks.

I have created the same code. There are some facts that need to be understood here.

extension MyProtocol {
    typealias ResponseType = MyDefaultDecodableType

    func handleResponse(data: Data) -> ResponseType {

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

    }
}

Conceptually, there are no generic protocols in Swift. But by using typealias we can declare a required alias for another type.

Your extension doesn't need to define typealias ResponseType = MyDefaultDecodableType as it is going to provide some default implementation using MyDefaultDecodableType , so it is useless.

So your extension would be something like this

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)

    }
}

Now you can define

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 {


}

Without any errors

Now if you use

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

You will get

test __lldb_expr_44.MyObject

test __lldb_expr_44.MyObject2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM