Документация

Настройка инициализации

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

Параметры инициализации

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

Следующий пример определяет структуру Celsius, которая хранит температуру в Цельсиях. Структура Celsius реализует два пользовательских инициализатора init(fromFahrenheit:) и init(fromKelvin:), которые инициализируют новый экземпляр структуры со значением другой температурной шкалы:

struct Celsius {
    var temperatureInCelsius: Double
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// boilingPointOfWater.temperatureInCelsius is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius is 0.0

Первый инициализатор имеет один параметр с внешнем именем fromFahrinheit и с локальным именем fahrenheit. Второй инициализатор имеет один параметр с внешнем именем fromKelvin и локальным именем kelvin. Оба инициализатора конвертируют их единственный аргумент в значение по Цельсию и сохраняют это значение в свойство temperatureInCelsius.

Локальные и внешние имена параметров

Как и в случае с параметрами функций или методов, параметры инициализации могут иметь локальные имена для использования внутри тела инициализатора и внешние для использования при вызове инициализатора.

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

Следующий пример определяет структуру Color с тремя постоянными свойствами red, green, blue. Эти свойства имеют значения от 0.0 до 1.0, для индикации количества соответствующего цвета.

Color имеет инициализатор с тремя параметрами red, green, blue типа Double(компоненты цвета красного, зеленого, синего). Так же Color имеет второй инициализатор с одним параметром white, который нужен для предоставления значения для всех трех компонентов цвета.

struct Color {
    let red, green, blue: Double
    init(red: Double, green: Double, blue: Double) {
        self.red   = red
        self.green = green
        self.blue  = blue
    }
    init(white: Double) {
        red   = white
        green = white
        blue  = white
    }
}

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

let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGray = Color(white: 0.5)

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

let veryGreen = Color(0.0, 1.0, 0.0)
// этот код вызовет ошибку компиляции, так как здесь нет внешних имен

Параметры инициализатора без внешних имен

Если вы не хотите использовать внешние имена для параметров инициализации, напишите подчеркивание (_) вместо явного указания внешнего имени для этого параметра, чтобы переопределить поведение по умолчанию.

Вот расширенный вариант для Celsius, который мы рассматривали ранее, с дополнительным инициализатором, для создания нового экземпляра Celsius с типом значения температуры Double только уже по шкале Цельсия:

struct Celsius {
    var temperatureInCelsius: Double
    init(fromFahrenheit fahrenheit: Double) {
        temperatureInCelsius = (fahrenheit - 32.0) / 1.8
    }
    init(fromKelvin kelvin: Double) {
        temperatureInCelsius = kelvin - 273.15
    }
    init(_ celsius: Double) {
        temperatureInCelsius = celsius
    }
}
let bodyTemperature = Celsius(37.0)
// bodyTemperature.temperatureInCelsius is 37.0

Инициализатор вызывает Celsius(37.0), что понятно и без внешнего имени параметра. Поэтому целесообразно написать init(_ celsius: Double), для того, чтобы предоставить безымянное значение типа Double.

Опциональные типы свойств

Если ваш пользовательский тип имеет свойство, которое логически имеет “отсутствие значения”, возможно потому, что его значение не может быть установлено во время инициализации или потому, что ему разрешается иметь “отсутствие значения” в какой-либо точке кода, то такое свойство нужно объявить с опциональным типом. Свойства опционального типа автоматически инициализируются со значением nil, указывая на то, что значение стремится иметь значение “пока что отсутствие значение” на этапе инициализации.

Следующий код определяет класс SurveyQuestion с опциональным типом String свойства response:

class SurveyQuestion {
    var text: String
    var response: String?
    init(text: String) {
        self.text = text
    }
    func ask() {
        print(text)
    }
}
let cheeseQuestion = SurveyQuestion(text: "Нравится ли вам сыр?")
cheeseQuestion.ask()
// Выведет "Нравится ли вам сыр?"
cheeseQuestion.response = "Да, я люблю сыр"

Ответ на вопрос не может быть известен до того, пока он не задан, так что свойство response должно быть типа String? (опциональный String). Ему автоматически присваивается значение nil при инициализации SurveyQuestion, значащее, что “значения пока нет”.

Присваивание значений постоянным свойствам во время инициализации

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

Заметка

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

Вы можете пересмотреть пример SurveyQuestion и использовать вместо переменного свойства text постоянное свойство text, для индикации того, что это свойство не меняется после создания SurveyQuestion. Даже если свойство является постоянным, оно все еще может быть установлено в инициализаторе класса:

class SurveyQuestion {
  let text: String
  var response: String?
  init(text: String) {
    self.text = text
  }
  func ask() {
    print(text)
  }
}
let beetsQuestion = SurveyQuestion(text: "Что насчет свеклы?")
beetsQuestion.ask()
// Выведет "Что насчет свеклы?"
beetsQuestion.response = "Я люблю свеклу, но не в сыром виде!"

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

Если вы создавали аккаунт ранее...

Если Вы создавали аккаунт на старой версии сайта, а сейчас не можете зайти, то Вам нужно сделать следующее:

  1. Нажать "Забыли пароль?"
  2. Указать Ваш email в появившейся форме и нажать "Сбросить пароль"
  3. Вам на почту придет письмо с уникальной ссылкой, по которой вы сможете сбросить старый пароль и войти в свой аккаунт на новой версии сайта

Далее вы сможете заходить на сайт по email и паролю.

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: