Деинициализация
Освобождение ресурсов, требующих пользовательской очистки.
Деинициализатор вызывается непосредственно перед тем, как экземпляр класса освобождается. Вы пишете деинициализаторы с помощью ключевого слова deinit, аналогично тому, как инициализаторы пишутся с помощью ключевого слова init. Деинициализаторы доступны только для типов классов.
Как работает деинициализация
Swift автоматически освобождает ваши экземпляры, когда они больше не нужны, чтобы освободить ресурсы. Swift обрабатывает управление памятью экземпляров через автоматическое управление ссылками (ARC), как описано в AutomaticReferenceCounting. Как правило, вам не нужно выполнять ручную очистку, когда ваши экземпляры освобождаются. Однако, когда вы работаете со своими собственными ресурсами, вам может потребоваться выполнить дополнительную очистку самостоятельно. Например, если вы создаете пользовательский класс для открытия файла и записи в него данных, вам может потребоваться закрыть файл перед тем, как экземпляр класса будет освобожден.
Определения классов могут иметь не более одного деинициализатора на класс. Деинициализатор не принимает никаких параметров и записывается без скобок:
deinit {
// perform the deinitialization
} Деинициализаторы вызываются автоматически, непосредственно перед освобождением экземпляра. Вам не разрешается вызывать деинициализатор самостоятельно. Деинициализаторы суперкласса наследуются их подклассами, и деинициализатор суперкласса вызывается автоматически в конце реализации деинициализатора подкласса. Деинициализаторы суперкласса всегда вызываются, даже если подкласс не предоставляет собственного деинициализатора.
Поскольку экземпляр не освобождается до тех пор, пока не будет вызван его деинициализатор, деинициализатор может получить доступ ко всем свойствам экземпляра, на котором он вызывается, и может изменить его поведение на основе этих свойств (например, поиск имени файла, который нужно закрыть).
Примеры использования деинициализаторов
Вот пример использования деинициализатора. В этом примере определены два новых типа, Bank и Player, для простой игры. Класс Bank управляет вымышленной валютой, которая никогда не может иметь более 10 000 монет в обращении. В игре может быть только один Bank, поэтому Bank реализован как класс с типовыми свойствами и методами для хранения и управления его текущим состоянием:
class Bank {
static var coinsInBank = 10_000
static func distribute(coins numberOfCoinsRequested: Int) -> Int {
let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
coinsInBank -= numberOfCoinsToVend
return numberOfCoinsToVend
}
static func receive(coins: Int) {
coinsInBank += coins
}
} Bank отслеживает текущее количество монет с помощью свойства coinsInBank. Он также предлагает два метода — distribute(coins:) и receive(coins:) — для обработки распределения и сбора монет.
Метод distribute(coins:) проверяет, достаточно ли монет в банке, прежде чем распределить их. Если монет недостаточно, Bank возвращает меньшее число, чем то, которое было запрошено (и возвращает ноль, если монет в банке не осталось). Он возвращает целочисленное значение, указывающее фактическое количество предоставленных монет.
Метод receive(coins:) просто добавляет полученное количество монет обратно в хранилище монет банка.
Класс Player описывает игрока в игре. Каждый игрок имеет определенное количество монет, хранящихся в его кошельке в любое время. Это представлено свойством игрока coinsInPurse:
class Player {
var coinsInPurse: Int
init(coins: Int) {
coinsInPurse = Bank.distribute(coins: coins)
}
func win(coins: Int) {
coinsInPurse += Bank.distribute(coins: coins)
}
deinit {
Bank.receive(coins: coinsInPurse)
}
} Каждый экземпляр Player инициализируется начальным количеством монет от банка во время инициализации, хотя экземпляр Player может получить меньше монет, если их недостаточно.
Класс Player определяет метод win(coins:), который извлекает определенное количество монет из банка и добавляет их в кошелек игрока. Класс Player также реализует деинициализатор, который вызывается непосредственно перед освобождением экземпляра Player. Здесь деинициализатор просто возвращает все монеты игрока в банк:
var playerOne: Player? = Player(coins: 100)
print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")
// Prints "A new player has joined the game with 100 coins"
print("There are now \(Bank.coinsInBank) coins left in the bank")
// Prints "There are now 9900 coins left in the bank" Создается новый экземпляр Player, с запросом на 100 монет, если они доступны. Этот экземпляр Player хранится в необязательной переменной Player, называемой playerOne. Здесь используется необязательная переменная, потому что игроки могут покинуть игру в любой момент. Необязательная переменная позволяет отслеживать, есть ли игрок в игре в данный момент.
Поскольку playerOne необязательная, она квалифицируется восклицательным знаком (!), когда обращаются к её свойству coinsInPurse для вывода его значения по умолчанию и всякий раз, когда вызывается метод win(coins:):
playerOne!.win(coins: 2_000)
print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")
// Prints "PlayerOne won 2000 coins & now has 2100 coins"
print("The bank now only has \(Bank.coinsInBank) coins left")
// Prints "The bank now only has 7900 coins left" Здесь игрок выиграл 2000 монет. Кошелек игрока теперь содержит 2100 монет, а в банке осталось только 7900 монет.
playerOne = nil
print("PlayerOne has left the game")
// Prints "PlayerOne has left the game"
print("The bank now has \(Bank.coinsInBank) coins")
// Prints "The bank now has 10000 coins" Теперь игрок покинул игру. Это показано установкой необязательной переменной playerOne в значение nil, что означает «нет экземпляра Player». В этот момент ссылка переменной playerOne на экземпляр Player прерывается. Никакие другие свойства или переменные больше не ссылаются на экземпляр Player, поэтому он освобождается для освобождения памяти. Непосредственно перед этим автоматически вызывается его деинициализатор, и его монеты возвращаются в банк.
This source file is part of the Swift.org open source project
Copyright © 2014 - 2025 Apple Inc. and the Swift project authors
Licensed under Apache License v2.0 with Runtime Library Exception