Поведение быстрых протоколов - PullRequest
0 голосов
/ 10 марта 2020

Предположим, у меня есть протокол FooProtocol в Swift с одним методом с реализацией по умолчанию:

protocol FooProtocol {
    func foo()
}

extension FooProtocol {
    func foo() {
        print("protocol")
    }
}

и класс FooClass с экземпляром приведения:

class FooClass : FooProtocol {
    func foo() {
        print("class")
    }
} 

let A = FooClass() as FooProtocol
A.foo()

Как и ожидалось, «класс» будет напечатан в консоли. Однако, если я сделаю метод foo () моего протокола необязательным - вместо него будет напечатан «protocol».

@objc protocol FooProtocol {
    @objc optional func foo() 
}

Но если я вызову A.foo? () Вместо A.foo () - «класс» будет напечатан снова.

Интересно, просто для теоретических целей, что, черт возьми, здесь происходит? Любые объяснения приветствуются.

1 Ответ

1 голос
/ 10 марта 2020

Вы не можете вызвать optional метод протокола без опциональной цепочки. Т.е. если вы закомментируете

extension FooProtocol {
    func foo() {
    ...

и попытаетесь вызвать A.foo(), вы получите ошибку компиляции:

значение необязательного типа '(() -> ( ))? должен быть развернут в значение типа '() -> ()'

Как видите, сигнатура необязательного не совпадает с необязательной. Таким образом, вызывая A.foo(), вы не вызываете метод, который вы реализовали, вы вызываете реализацию протокола по умолчанию напрямую.

Это также имеет смысл, поскольку основная причина для @objc optional - это интерполяция с Objective C, где реализация протокола по умолчанию не будет видна. Таким образом, использование функции протокола для функции obj c приведет к разным результатам для быстрой и объективной c, что нежелательно.

Я не могу сказать, есть ли лазейка для использования и optional, и реализации протокола по умолчанию на той же функции. Но вопрос: вам это действительно нужно?

Если вас интересует интерполяция, вам нужно одинаковое решение как для Swift, так и для Objective c, а это означает, что вам скорее нужна базовая реализация протокола c, которую Swift и obj c могут наследовать

Если вам не нужна интерполяция, вам не нужно опционально, и вы можете полагаться только на реализацию протокола по умолчанию.

...