Разница при объявлении протокола Swift с использованием наследования от другого протокола или с использованием где Self - PullRequest
4 голосов
/ 12 июля 2019

Я до сих пор не понимаю, в чем разница при объявлении протокола Swift с использованием наследования:

protocol SubProtocol: SuperProtocol { ... }

или используя where Self

protocol SubProtocol where Self: SuperProtocol { ... }

При выполнении этих двух способов результаты абсолютно одинаковы, обе опции компилируются нормально, и это работает, SubProtocol будет иметь то же, что и SuperProtocol. Так в чем же разница?

Единственное различие, которое я вижу, - это семантика, одно более ясное, чем другое (см. Пример ниже). Но это моя точка зрения, и я хотел бы знать, думает ли кто-то еще так же, или, может быть, я не совсем понимаю все это.

Пример:

protocol Progressable {
    var isInProgress: Bool { get }
}

protocol Downloadable: Progressable {
    func download()
}

protocol ProgressReporting where Self: Progressable {
    func reportProgress() -> Bool
}

Для меня Downloadable имеет смысл, что он наследуется от Progressable, каждая загрузка является прогрессивной, так что все в порядке.

Но ProgressReporting необязательно нужно наследовать от Progressable, для меня было бы более разумно ограничить его, используя, где, таким образом, читатель может знать, что тот, кто его реализует, должен будет соответствовать Progressable тоже (см. комментарии к коду ниже), вот когда я думаю, что семантика отличается.

class MyClassA: Downloadable {
    var isInProgress: Bool { return true }
    func download() {}

    func foo() {
        /*
         I have access to `self.isInProgress` because this class conforms `Downloadable`
         which inherits from `Progressable`, so this makes sense
         */
        _ = self.isInProgress
    }
}

class MyClassB: ProgressReporting {
    var isInProgress: Bool { return true }
    func reportProgress() {}

    func foo() {
        /*
         I have access to `self.isInProgress` but according to `ProgressReporting` definition,
         this class should be `Progressable` which is not, at least not explicitely
         */
        _ = self.isInProgress
    }
}

Я был бы признателен, если бы кто-то мог объяснить мне, в чем различия ?

Заранее спасибо.

1 Ответ

2 голосов
/ 12 июля 2019

Говоря о Swift5, нет никакой разницы между двумя формами, см. Примечания к выпуску Swift 5 :

Протоколы теперь могут ограничивать свои соответствующие типы теми, которые подклассируют данныйучебный класс.Поддерживаются две эквивалентные формы:

protocol MyView: UIView { /*...*/ }
protocol MyView where Self: UIView { /*...*/ } 

Swift 4.2 принял вторую форму, но она не была полностью реализована и иногда могла давать сбой во время компиляции или во время выполнения.(SR-5581) (38077232)

...