Видеокурсы по изучению языка программирования Swift. Подробнее

Деинициализаторы в действии

Если вы нашли опечатку в тексте, выделите ее и нажмите CTRL + ENTER.

Здесь приведен пример деинициализатора в действии. Для создания простой игры в этом примере определяются два новых типа Bank и Player. Структура Bank управляет наличностью, которой не может быть больше 10000 монет в обороте. В игре может быть только один 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 так же реализует деинициализатор, который вызывается сразу после того, как экземпляр освобождается. В примере ниже деинициализатор просто возвращает все монеты игрока в банк:

var playerOne: Player? = Player(coins: 100)
print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")
// Выведет "A new player has joined the game with 100 coins"
print("There are now \(Bank.coinsInBank) coins left in the bank")
// Выведет "There are now 9900 coins left in the bank"

Новый экземпляр Player создан со 100 монетами, если такое количество есть в банке. Экземпляр хранит опциональную переменную playerOne типа Player. Опциональный тип используется здесь, поскольку игрок может покинуть игру в любой момент. Опционал позволяет вам отслеживать присутствие игрока в игре.

Так как playerOne является опционалом, то используем восклицательный знак (!), когда мы хотим получить доступ к его свойству coinsInPurse или когда вызываем метод winCoins(_:):

playerOne!.win(coins: 2_000)
print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")
// Выведет "PlayerOne won 2000 coins & now has 2100 coins"
print("The bank now only has \(Bank.coinsInBank) coins left")
// Выведет "The bank now only has 7900 coins left"

Здесь наш игрок выиграл 2000 монет. Теперь у него в кошельке 2100 монет, соответственно, в банке осталось 7900 монет.

playerOne = nil
print("PlayerOne has left the game")
// Выведет "PlayerOne has left the game"
print("The bank now has \(Bank.coinsInBank) coins")
// Выведет "The bank now has 10000 coins"

Игрок покинул игру. Это осуществимо, если мы присвоим опционалу playerOne значение nil, что значит, что игрока больше нет. На этот момент мы больше не имеем доступа к свойствам или методам переменной playerOne, то есть у нас не стало ссылки на экземпляр класса Player, так что экземпляр освобождается и освобождается память. Прямо перед тем как это случится, автоматически вызывается деинициализатор, который возвращает монеты в банк.

 

Swift: 
4.0