Расширение протокола Initializer заставляет вызывать self.init - PullRequest
0 голосов
/ 10 мая 2018

Я только что прочитал документ Apple Swift 4, касающийся требований инициализатора протокола, и предоставлял реализацию по умолчанию в расширении протокола.

import UIKit
protocol Protocol {
    init()
}
extension Protocol {
    init() {
        print("SDf")
        self.init() // Line 1
                    // Compiler error occured if this is omitted 
                    //"'self.init' isn't called on all paths before returning from initializer"
    }
}

struct Structure: Protocol {
    init(string: String) {

    }
}

Structure()      // Line 2

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

Теперь, зная это, если я удалю строку 1, компилятор выдаст ошибку.

Q. Почему это заставляет меня использовать self.init() в строке 1, и как я могу выйти из этой ситуации?

1 Ответ

0 голосов
/ 10 мая 2018

Рассмотрим этот пример:

protocol P {
  init()
}

extension P {
  init() {

  } // error: 'self.init' isn't called on all paths before returning from initializer
}

struct S : P {
  var str: String
}

let s = S()
print(s.str)

Предположим, что оно скомпилировано - мы сможем создать значение S без предоставления значения для свойства str. Вот почему компилятор жалуется, что ваша реализация расширения протокола init() не вызывает self.init. Требуется, чтобы вы подключились к некоторым другим требованиям инициализатора - тем, для которого вы не предоставляете реализацию по умолчанию (в противном случае вы могли бы попасть в рекурсивный цикл, как вы узнали), и, следовательно, к тому, что принятие Тип должен быть реализован так, чтобы он мог полностью инициализировать себя.

Например, это законно:

protocol P {
  init()
  init(str: String)
}

extension P {
  init() {
    self.init(str: "some default")
  }
}

struct S : P {
  var str: String
}

let s = S()
print(s.str) // some default

потому что теперь мы подключаемся к требованию init(str:), которое S должно реализовать (в этом случае оно удовлетворяется неявным членным инициализатором ).

...