Что делает init! (), Что отличается от init ()? [Дубликат]

Вы можете попробовать плагины jQuery для проверки надежности пароля

Некоторые из них -

Счетчик прочности пароля

Индикатор силы пароля

3
задан Dave Gallagher 23 July 2015 в 21:33
поделиться

3 ответа

В подавляющем большинстве случаев вы должны использовать init, а не init!. Есть несколько случаев, когда требуется init!. Наиболее распространенным в моем опыте является то, что инициализатор «должен преуспеть» хочет вызвать неудачный инициализатор. Рассмотрим этот случай:

struct NotEmpty {
    let something: String
    init?(something: String) {
        guard !something.isEmpty else { return nil }
        self.something = something
    }

    init() {
        self.init(something: "unknown")! // <-- This is illegal
    }
}

Мы знаем, что init() будет успешным, потому что мы передаем непустую строку. Но нет способа выразить это стандартным инициализатором (и компилятор не может доказать, что это так или иначе). Вместо этого нам нужно использовать init!:

init!() {
    self.init(something: "unknown")
}

Теперь вызывающий может обрабатывать результат так, как если бы он не был необязательным (на самом деле он), хотя в соответствии с типами он мог провалился. Это будет ошибка программирования, и вы потерпите крах. ! здесь в основном говорит: «Да, я знаю, что это может потерпеть неудачу, но я обещаю, что этого никогда не будет». И в Swift «обещание» означает «или, пожалуйста, проваливайте».

7
ответ дан Rob Napier 16 August 2018 в 10:00
поделиться
  • 1
    не могли бы вы рассказать немного больше о том, почему «self.init» (что-то: «неизвестно»)! & quot; незаконно? Большое спасибо! – user 17 March 2016 в 08:12
  • 2
    Вызов self.init(something: "unknown") возвращает Необязательный. Он вызывается из init(), который возвращает необязательный параметр. – Rob Napier 17 March 2016 в 13:13

Вы можете использовать его в классах, чтобы переопределить инициализатор с ошибкой и сделать его невоспроизводимым.

Такая же осторожность должна применяться при работе с неявно разворачиваемой: это может быть опасно, потому что у нее есть возможность сделать сбой приложения.

0
ответ дан Antonio 16 August 2018 в 10:00
поделиться

Вы можете делегировать из init? инициализировать! и наоборот, и вы можете переопределить init? внутри! и наоборот.

Это означает, что вы можете конвертировать некоторые init? в init!, если вы уверены, что это не сработает или наоборот. В документации есть пример:

enum TemperatureUnit {
    case Kelvin, Celsius, Fahrenheit
        init?(symbol: Character) {
        switch symbol {
        case "K":
            self = .Kelvin
        case "C":
            self = .Celsius
        case "F":
            self = .Fahrenheit
        default:
            return nil
        }
    }
}

У вас может быть похожий код, и вы можете инициализировать его только с помощью констант, не используя пользовательский ввод, или некоторые другие источники ввода. Поэтому вы уверены, что это не подведет, почему бы не сделать это init!?

1
ответ дан KleMiX 16 August 2018 в 10:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: