Недавно Apple представила общественности достаточно важное изменение в разработке iOS приложений, анонсировав новый язык программирования Swift. В настоящее время, количество материалов на русском, посвящённых этому языку, ограничено. Также Swift — язык объектно-ориентированный, и классы в нём — основа основ. Поэтому я решил перевести эту статью.
Создание классов
Для создания новых классов используется ключевое слово class
, название класса и фигурные скобки, внутри которых объявляются свойства и методы класса.
class Point {
var x = 0.0 // sets the default value of x to 0
var y = 0.0 // sets the default value of x to 0
}
// this creates a new Point instance using the default initializer
var point = Point()
point.x = 100 // sets the x property to 100
point.y = 200 // sets the y property to 200
Инициализаторы
Из официальной документации Apple:
Инициализация — процесс подготовки экземпляра класса, структуры или перечисления для дальнейшего использования. Он включает в себя инициализацию каждого свойства и выполнение других настроек или инициализаций, необходимых до первого использования.
Процесс инициализации реализуется с помощью инициализаторов, которые являются специальными методами, вызывающимися при объявлении новых экземпляров класса. В отличие от Objective-C, в Swift инициализаторы ничего не возвращают, т.к. они обеспечивают правильность инициализации новых экземпляров класса.
Обратимся к примеру
class Point {
var x
var y
}
Запустив его, вы получите три ошибки компиляции
class Point { // Class 'Point' has no initializers (класс <code>Point</code> не содержит инициализаторов)
var x // Type annotation missing in pattern (Отсутствует аннотация типа)
var y // Type annotation missing in pattern (Отсутствует аннотация типа)
}
Чтобы исправить ситуацию, давайте зададим тип каждого свойства
class Point {
var x: Double
var y: Double
}
Инициализатор задаётся ключевым словом init
. У инициализатора может быть несколько параметров, а может их вообще не быть
class Point {
var x: Float
var y: Float
init(x: Float, y: Float) {
self.x = x
self.y = y
}
}
// Example usage
var point = Point(x: 100, y: 200)
Также мы можем установить опциональные значения свойств. Чтобы это сделать, просто поставьте ?
после типа, как показано в примере. Если объявить свойство подобным образом, то оно будет иметь значение по умолчанию nil
.
class Point {
var x: Float?
var y: Float?
}
var point = Point() // both the x and y properties are now set to nil
point.x = 100.0
point.y = 200.0
Перегрузка инициализаторов
Представим, что во время создания проекта появилась необходимость использовать список пользователей. Давайте для начала создадим класс User
. Каждый объект класса будет иметь следующие поля: имя (firstName
), фамилию (lastName
), краткую информацию о пользователе (bio
). Поля имени и фамилии будут иметь опциональные значения, а поле краткой информации — значение по умолчанию (т.е. это поле будет дополнительным).
class User {
var firstName: String?
var lastName: String?
var bio: String = "I ♡ Swift!"
}
var user = User() // user = { firstName: nil, lastName: nil, bio: "I ♡ Swift!"}
Ну что ж, класс мы написали. Теперь пришло время создать первых пользователей. Поле краткой информации — дополнительное, значит нам нужно перегрузить инициализатор, т.к. можно как написать что-то про игрока, так и оставить его тёмной личностью. Ну что ж, давайте напишем инициализаторы для обоих случаев
class User {
var firstName: String
var lastName: String
var bio: String = "I ♡ Swift!"
// no bio provided
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
// bio provided
init(firstName: String, lastName: String, bio: String) {
self.firstName = firstName
self.lastName = lastName
self.bio = bio
}
}
var me = User(firstName: "Andrei", lastName: "Puni")
// me = { firstName: "Andrei", lastName: "Puni", bio: "I ♡ Swift!"}
var silviu = User(firstName: "Silviu", lastName: "Pop", bio: "I f**ing ♡ Swift!!!")
// silviu = { firstName: "Silviu", lastName: "Pop", bio: "I f**ing ♡ Swift!!!"}
Однако согласитесь, это не совсем рационально, ведь отличия в инициализации минимальные — про кого-то есть какая-то информация, а про кого-то — нет. Поэтому давайте напишем один инициализатор, а аргументу bio
дадим значение по умолчанию.
class User {
var firstName: String
var lastName: String
var bio: String
init(firstName: String, lastName: String, bio: String = "I ♡ Swift!") {
self.firstName = firstName
self.lastName = lastName
self.bio = bio
}
}
var me = User(firstName: "Andrei", lastName: "Puni")
// me = { firstName: "Andrei", lastName: "Puni", bio: "I ♡ Swift!"}
var silviu = User(firstName: "Silviu", lastName: "Pop", bio: "I f**ing ♡ Swift!!!")
// silviu = { firstName: "Silviu", lastName: "Pop", bio: "I f**ing ♡ Swift!!!"}
Идентичность классов
Из официальной документации Apple:
Операторы идентичности
Поскольку класс является ссылочным типом, может возникнуть ситуация, когда один и тот же экземпляр класса обозначается несколькими переменными или константами. (Это невозможно для структур и перечислений, т.к. и те, и другие являются значимыми типами и копируются при присваивании и передаче в функцию в качестве параметров)
Иногда полезно выяснить, что две переменные или константы ссылаются на один и тот же экземпляр класса. Для этого в Swift существуют два оператора:
Идентичны (===
)
Не идентичны (!==
)
Предположим, что у нас есть список игроков, один из них — владелец замка. Нам необходимо добавить какие-то функции для игроков, не являющихся владельцами замка. Для этого давайте используем оператор идентичности (===
)
var users: User[] = [ ... ] // User[] means Array of Users
var host = /* some user */
for user in users {
if user === host {
// host logic here
println("this is the host")
} else {
// guest logic here
println("this is a guest")
}
}
Оператор равенства ==
не работает при сравнении объектов классов, так что вам не следует бояться подобных ошибок.
В следующей части мы рассмотрим наследование классов и протоколы.
Автор: DrhF