Swift 2.0: Расширения протокола: два протокола с той же ошибкой компиляции подписи функции

Учитывая два протокола и их расширения:

protocol FirstDelegate {
    func someFunc()
}

protocol SecondDelegate {
    func someFunc()
}

extension FirstDelegate {
    func someFunc() {
        print("First delegate")
    }
}

extension SecondDelegate {
    func someFunc() {
        print("Second delegate")
    }
}

и попытаться соответствовать их обоим:

class SomeClass: FirstDelegate, SecondDelegate {}

Я получаю ошибку времени компиляции:

Тип "SomeClass" не соответствует протоколу "FirstDelegate"

Обмен FirstDelegate и SecondDelegate:

class SomeClass: SecondDelegate, FirstDelegate {}

производит обратное:

Тип "SomeClass" не соответствует протоколу "SecondDelegate"

Удаление одного из расширений устраняет проблему. То же самое обеспечивает реализацию someFunc() внутри SomeClass.

Эта функциональность расширения протокола для меня довольно нова. Кроме того, информация о нем в официальном "Руководстве по быстрому программированию" (Prerelease) в Apple пока мало.

Я нарушил некоторые правила расширений протокола здесь?

Ответы

Ответ 1

Протокол определяет требования (методы, свойства,...) для совместимый тип.

protocol FirstDelegate {
    func someFunc()
}

protocol SecondDelegate {
    func someFunc()
}

определяет два протокола с тем же требуемым методом someFunc(). Соответствующий тип должен реализовать этот метод:

class SomeClass: FirstDelegate, SecondDelegate {
    func someFunc() {
        print("SomeClass implementation")
    }
}

Расширение протокола обеспечивает реализацию методов и свойств к соответствующим типам. Частным случаем расширения протокола является по умолчанию, который вы определили здесь:

extension FirstDelegate {
    func someFunc() {
        print("First delegate")
    }
}

Он определяет реализацию по умолчанию someFunc() для всех типов в соответствии с FirstDelegate. Поскольку это единственное требование метод этого протокола, соответствующий класс не должен определять метод вообще:

class SomeClass: FirstDelegate {

}

SomeClass().someFunc() // Output: First delegate

Но если класс предоставляет свою собственную реализацию, то будет использоваться:

class SomeClass: FirstDelegate {
    func someFunc() {
        print("SomeClass implementation")
    }
}

SomeClass().someFunc() // Output: SomeClass implementation

В вашем случае вы определили реализации по умолчанию someFunc() для обоих протоколов:

extension FirstDelegate {
    func someFunc() {
        print("First delegate")
    }
}

extension SecondDelegate {
    func someFunc() {
        print("Second delegate")
    }
}

Класс может по-прежнему соответствовать обоим протоколам, если он предоставляет свои собственные реализация требуемого метода:

class SomeClass: FirstDelegate, SecondDelegate {
    func someFunc() {
        print("SomeClass implementation")
    }
}

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

class SomeClass: FirstDelegate, SecondDelegate {

}

для обоих протоколов потому что есть конфликт. Он не указан, который по умолчанию следует использовать реализацию, и почему компилятор жалуется.

На самом деле класс теперь не соответствует ни одному протоколу. Это можно увидеть в полном журнале компилятора в навигаторе отчетов:

main.swift:24:7: error: type 'SomeClass' does not conform to protocol 'FirstDelegate'
class SomeClass: FirstDelegate, SecondDelegate {
      ^
main.swift:5:10: note: multiple matching functions named 'someFunc()' with type '() -> ()'
    func someFunc()
         ^
main.swift:19:10: note: candidate exactly matches
    func someFunc() {
         ^
main.swift:13:10: note: candidate exactly matches
    func someFunc() {
         ^
main.swift:24:7: error: type 'SomeClass' does not conform to protocol 'SecondDelegate'
class SomeClass: FirstDelegate, SecondDelegate {
      ^
main.swift:9:10: note: multiple matching functions named 'someFunc()' with type '() -> ()'
    func someFunc()
         ^
main.swift:19:10: note: candidate exactly matches
    func someFunc() {
         ^
main.swift:13:10: note: candidate exactly matches
    func someFunc() {
         ^