본문 바로가기
프로그래밍/Swift

[Swift] Deinitialization

by 별준 2022. 1. 6.

References

Contents

  • How Deinitialization Works
  • Deinitializers in  Action

deinitializer는 클래스 인스턴스가 해제될 때 즉시 호출됩니다. deinitializer는 deinit 키워드를 사용하여 작성할 수 있으며, init 키워드를 사용하여 initializer를 작성하는 방법과 유사합니다. Deinitializer는 오직 class 타입에서만 사용할 수 있습니다.

 


How Deinitialization Works

Swift는 인스턴스가 더 이상 필요없을 때, 자동으로 인스턴스를 할당 해제하여 리소스를 해제합니다. Swift는 인스턴스의 메모리 관리를 automatic reference counting(ARC)를 통해 관리합니다. 일반적으로 수작업으로 해제할 필요가 없습니다. 그러나 인스턴스 자체 리소스를 가지고 작업할 때, 몇 가지 해제 작업이 수행할 필요가 있을 때도 있습니다. 예를 들어, 만약 파일을 열고, data를 파일에 작성하는 클래스를 생성한다면, 인스턴스가 해제되기 전에 파일을 닫는 것이 필요합니다.

 

클래스 정의에서 최대 하나의 deinitializer를 가질 수 있습니다. deinitializer는 어떠한 파라미터도 전달받지 않으며, 괄호()없이 작성됩니다.

deinit {
    // perform the deinitialization
}

Deinitializer는 자동으로 호출되며, 인스턴스 할당 해제가 발생하기 전에 호출됩니다.

직접 deinitializer를 호출할 수는 없습니다. 수퍼클래스의 deinitializer는 수퍼클래스의 서브클래스에 의해 상속되고, 수퍼클래스의 deinitializer는 자동으로 서브클래스의 deinitializer의 끝에서 호출됩니다. 서브클래스가 자신만의 deinitializer를 가지고 있지 않더라도, 수퍼클래스의 deinitializer는 항상 호출됩니다.

 

인스턴스는 deinitializer가 호출될 때까지 해제되지 않으므로, deinitializer는 호출된 인스턴스의 모든 속성에 액세스할 수 있으며, 이러한 속성들을 기반(닫아야하는 파일 이름 탐색)으로 동작을 수정할 수 있습니다.

 


Deinitializers in Action

아래의 코드는 deinitializer 예제 코드입니다. 이 코드에서는 간단한 게임을 위해 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:)와 recieve(coins:)라는 두 개의 메소드는 코인의 distribution과 collection을 관리합니다.

distribute(coins:) 메소드는 코인을 분배하기 전에 충분한 양의 코인이 은행에 있는지 체크합니다. 만약 충분한 코인이 없다면 Bank는 요청된 코인보다 더 적은 수의 코인을 반환합니다. 만약 은행에 코인이 하나도 없다면 0을 반환합니다.

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 클래스는 win(coins:) 메소드를 정의하는데, 이 메소드는 은행에서 일정 수의 코인을 받아서 플레이어의 지갑에 추가합니다. 또한 Player 클래스는 인스턴스가 해제되기 전에 호출되는 deinitializer도 구현합니다. 이는 플레이어의 모든 코인을 다시 은행에 반납하도록 구현되어 있습니다.

 

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 인스턴스는 optional Player 변수인 playerOne에 저장됩니다. Optional 변수가 사용된 이유는 플레이어가 언제든지 게임을 떠날 수 있기 때문입니다. Optional은 플레이어가 현재 게임이 있는지를 추적할 수 있게 해줍니다.

 

playerOne이 optional이기 때문에 기본 코인 갯수를 출력하기 위해 coinsInPurse 속성에 액세스하거나 win 메소드를 호출할 때마다 느낌표(!)를 붙여주어야 합니다.

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"

이제 플레이어가 게임을 떠났습니다. 이는 optional playerOne 변수의 값을 nil로 설정하면됩니다. 이렇게 되는 순간 playerOne 변수의 Player 인스턴스의 참조는 깨집니다. Player 인스턴스를 참조하는 다른 속성이나 변수가 없으므로 메모리를 확보하기 위해서 인스턴스의 할당이 해제됩니다. 해제가 되기 전에 deinitializer는 자동으로 호출되고 인스턴스의 코인은 다시 은행으로 반환됩니다.

 

 

'프로그래밍 > Swift' 카테고리의 다른 글

[Swift] Type Casting  (0) 2022.01.29
[Swift] Optional Chaining  (0) 2022.01.08
[Swift] Initialization  (0) 2022.01.03
[Swift] Inheritance (상속)  (0) 2021.12.30
[Swift] Subscripts (서브스크립트)  (0) 2021.12.30

댓글