Расширение протокола Swift со свойством, соответствующим протоколу

Я объявил такой протокол

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

Здесь JSONSerializable не является фактическим типом, это еще один протокол, который я объявил так:

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

Фактически, для этого протокола JSONConnection требуется переменная с именем jsonRootObject, которая просто должна соответствовать протоколу JSONSerializable.

Отлично.


Теперь о реализациях.

Я создал класс JSONStockDetailRootObject, который соответствует протоколу JSONSerializable.

class JSONStockDetailRootObject: JSONSerializable

И я хотел создать класс StockConnection, соответствующий протоколу JSONConnection.

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

Я думал, что если бы у меня была переменная jsonRootObject типа, который соответствовал протоколу JSONSerializable, то этот класс StockConnection, в свою очередь, соответствовал бы протоколу JSONConnection ... но нет.

Компилятор утверждает: «Протокол требует свойства 'jsonRootObject' с типом 'JSONSerializable?'

Что мне не хватает? Спасибо


person Frédéric Adda    schedule 14.02.2016    source источник
comment
вы изменили тип jsonRootObject. Теперь это больше не соответствует.   -  person R Menke    schedule 14.02.2016


Ответы (1)


В вашем примере класс StockConnection не содержит какой-либо допустимой реализации плана var jsonRootObject: JSONSerializable? { get set }, который он обещает реализовать в соответствии с JSONConnection. Обратите внимание, что в контексте jsonRootObject, JSONSerializable является типом, и даже если JSONStockDetailRootObject соответствует JSONSerializable, его нельзя рассматривать как тот же тип .

Вы можете решить эту проблему, введя псевдонимы, скажем, T (для использования в качестве типа jsonRootObject) в протокол JSONConnection; где T ограничивается типами, соответствующими 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?
}

Поскольку JSONStockDetailRootObject соответствует JSONSerializable, реализация jsonRootObject в StockConnection выше является действительным соответствием чертежа var jsonRootObject: T? { get set } в протоколе JSONConnection.

person dfrib    schedule 14.02.2016
comment
Отлично, сработало! Спасибо за очень четкое объяснение! - person Frédéric Adda; 14.02.2016
comment
@FredA. Рад помочь. - person dfrib; 14.02.2016
comment
Выполнение этого сегодня вызывает ошибку о том, что для псевдонима типа требуется связанный тип, что вызывает целый ряд других ошибок. - person Bot; 30.04.2021
comment
@Bot Я не трогал Swift несколько лет, но не стесняйтесь обновлять этот ответ по своему усмотрению, если вы решите весь беспорядок других ошибок. - person dfrib; 01.05.2021