Инициализаторы
Инициализация представляет процесс подготовки объекта класса, структуры или перечисления к использованию. Этот процесс может включать установку начальных значений для свойств класса.
Для создания объекта класса используется инициализатор. Каждый класс имеет инициализатор по умолчанию:
1
2
3
4
5
6
7
class User {
var age: Int = 0
var name: String = ""
}
var tom: User = User()
Выражение User() преставляет вызов инициализатора.
Важно, что хранимые свойства класса (то есть переменные и константы) должны быть инициализированы и иметь определенное значение ко времени создания объекта класса. В данном случае свойствам класса name и age напрямую присваиваются значения. Но также для инициализации свойств может использоваться инициализатор.
Для переопределения инициализатора в классе нам надо использовать ключевое слово init:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class User {
var age: Int
var name: String
init(){
age = 22
name = "Tom"
}
func getUserInfo(){
print("Имя: \(name); возраст: \(age)")
}
}
var tom: User = User()
tom.getUserInfo() // Имя: Tom; возраст: 22
Стоит отметить, что так как переменным name и age не присваиваются начальные значения, а их инициализация производится в инициализаторе, то можно определить эти переменные как константы:
1
2
3
4
5
6
7
8
9
10
11
class User {
let age: Int
let name: String
init(){
age = 22
name = "Tom"
}
}
Фактически инициализатор представляет функцию, которая выполняет начальную инициализацию объекта.
При необходимости мы можем определять дополнительные инициализаторы:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class User {
var age: Int
var name: String
init(){
age = 22
name = "Tom"
}
init(name: String, age: Int){
self.age = age
self.name = name
}
func getUserInfo(){
print("Имя: \(self.name); возраст: \(self.age)")
}
}
var bob: User = User(name: "Bob", age: 34)
bob.getUserInfo() // Имя: Bob; возраст: 34
Второй инициализатор принимает два параметра name и age для установки свойств класса. Так как параметры и свойства класса называются одинаково, то для их разграничения вместе с названиями свойств используется ключевое слово self.
И при создании объекта в данном случае используется второй инициализатор: var bob: User = User(name: "Bob", age: 34)
Инициализаторы могут определять значения по умолчанию для параметров. Так, пример выше мы могли бы сократить следующим образом:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class User {
var age: Int
var name: String
init(name: String = "Tom", age: Int = 22){
self.age = age
self.name = name
}
func getUserInfo(){
print("Имя: \(self.name); возраст: \(self.age)")
}
}
var tom = User()
tom.getUserInfo() // Имя: Tom; возраст: 22
Делегирование инициализации
Одни инициализаторы могут вызывать другие. Вызывающие инициализаторы должны быть определены с ключевым словом convenience:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class User {
var age: Int
var name: String
convenience init(){
self.init(name: "Tom", age: 22)
}
init(name: String, age: Int){
self.age = age
self.name = name
}
func getUserInfo(){
print("Имя: \(self.name); возраст: \(self.age)")
}
}
var tom: User = User()
tom.getUserInfo() // Имя: Tom; возраст: 22
Failable-инициализаторы
Специальная разновидность инициализаторов (Failable Initializer) позволяет возвратить значение nil, если в процессе инициализации объекта произошла какая-нибудь ошибка. Например:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class User{
var name: String
var age: Int
init?(name: String, age: Int){
self.name = name
self.age = age
if(age < 0){
return nil
}
}
}
var bob: User = User(name: "Bob", age: 34)!
print(bob.name) // Bob
Поскольку пользователь, представленный классом User, в принципе не может иметь возраст меньше нуля. Поэтому ситуация, когда для возраста передается число меньше нуля, может рассматриваться как ошибочная. И в этом случае мы как раз можем использовать failable-инициализатор.
Для определения такого инициализатора после слова init ставится знак вопроса, а в самом инициализаторе можно предусмотреть ситуацию, при которой он возвращает значение nil:
1
2
3
4
5
6
7
8
init?(name: String, age: Int){
self.name = name
self.age = age
if(age < 0){
return nil
}
}
Возвращая nil, мы тем самым указываем, что мы не можем создать объект User по тем данным, которые переданы в инициализатор.
Важно учитывать, что объект, создаваемый этим инициализатором, будет представлять не тип User, а тип User?. Поэтому для получения значения нам надо еще использовать операцию ! (восклицательный знак):
1
var bob: User = User(name: "Bob", age: 34)!
Либо мы можем напрямую работать с объектом User?:
1
var bob: User? = User(name: "Bob", age: 34)
Однако надо учитывать, что если мы передадим неправильные данные, то инициализатор возвратит nil, и получение значение окончится ошибкой. Поэтому в таких случаях перед использованием объекта мы можем проверять на наличие значения:
1
2
3
if let lora = User(name: "Lora Palmer", age: -4){
print(lora.name)
}