Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift protocol extension with property conforming to protocol

I declared a protocol like so

protocol JSONConnection {
  var request: NSURLRequest { get set }
  var session: NSURLSession { get set }
  var jsonRootObject: JSONSerializable? { get set }
}

Here, the JSONSerializable is not an actual type, it is another protocol that I declared like so:

protocol JSONSerializable {
  func readFromJSON(json: JSON) throws
}

So, in fact, this JSONConnection protocol requires a variable called jsonRootObject that just needs to conform to the JSONSerializable protocol.

Fine.


Now, for the implementations.

I created a class called JSONStockDetailRootObject that conforms to the JSONSerializable protocol.

class JSONStockDetailRootObject: JSONSerializable

And I wanted to create a StockConnection class that conforms to the JSONConnection protocol.

class StockConnection: JSONConnection {
  var request: NSURLRequest
  var session: NSURLSession
  var jsonRootObject: JSONStockDetailRootObject?
}

I thought that, if I had a jsonRootObject variable of a type that conformed to the JSONSerializable protocol, then this class StockConnection would in turn conform to the JSONConnection protocol ... but no.

The compiler claims: "Protocol requires property 'jsonRootObject' with type 'JSONSerializable?'

What am I missing? Thanks

like image 938
Frédéric Adda Avatar asked Feb 14 '16 09:02

Frédéric Adda


1 Answers

In your example, the class StockConnection does not contain any valid implementation of the blueprint var jsonRootObject: JSONSerializable? { get set }, which it promises to implement by conforming to JSONConnection. Note that in the context of jsonRootObject, JSONSerializable is a type, and even if JSONStockDetailRootObject conforms to JSONSerializable, it cannot be treated as the same type.

You can solve this by introducing a typealias, say T, (to use as jsonRootObject type) into protocol JSONConnection; where T is constrained to types conforming to JSONSerializable.

protocol JSONSerializable {
    func readFromJSON(json: JSON) throws
}

protocol JSONConnection {
    typealias T: JSONSerializable
    var request: NSURLRequest { get set }
    var session: NSURLSession { get set }
    var jsonRootObject: T? { get set }
}

class JSONStockDetailRootObject: JSONSerializable {
    func readFromJSON(json: JSON) throws ...
}

class StockConnection: JSONConnection {
    var request: NSURLRequest = NSURLRequest()
    var session: NSURLSession = NSURLSession()
    var jsonRootObject: JSONStockDetailRootObject?
}

Since JSONStockDetailRootObject conforms JSONSerializable, the implementation of jsonRootObject in StockConnection above is valid conformance of the blueprint var jsonRootObject: T? { get set } in protocol JSONConnection.

like image 167
dfrib Avatar answered Sep 28 '22 06:09

dfrib