티스토리 뷰

반응형

이번 글에서는 Swift 공식 문서의 15번째 단원인 Deinitialization을 읽고 정리한 글을 쓰려고 한다.

Apple Swift 공식문서 15단원 - Deinitialization

 

Deinitialization

Deinitializer(소멸자)는 클래스 인스턴스의 메모리 할당이 해제되기 직전에 호출된다. Initializer가 init 키워드로 작성되는 방식과 비슷하게 Deinitializer는 deinit 키워드로 작성한다. 소멸자는 클래스에서만 사용할 수 있다


How Deinitialization Works

Swift는 더 이상 필요하지 않은 인스턴스를 자동으로 메모리 할당을 해제하여 리소스를 확보한다. Swift는 인스턴스의 메모리를 Automatic Reference Counting(ARC)를 통해 관리한다. 보통 인스턴스가 메모리 해제될 때 직접 정리할 필요는 없지만 자체 리소스를 사용하는 경우엔 몇 가지 추가적인 정리를 직접 해야 될 수도 있다. 예를 들어 커스텀 클래스를 만들어 파일을 열고 일부 데이터를 사용하는 경우 클래스 인스턴스가 할당 해제되기 전에 파일을 닫아야 한다.

 

클래스는 최대 한 개의 소멸자가 있을 수 있으며 소멸자는 매개변수를 사용하지 않으며 괄호도 필요없다.

deinit {
    // perform the deinitialization
}

위의 코드와 같이 소멸자를 작성해주면 된다.

 

소멸자는 인스턴스가 할당 해제되기 직전에 자동으로 호출된다. 하지만 소멸자를 직접 호출할 수는 없고 슈퍼 클래스의 소멸자는 서브 클래스에 상속되며 서브 클래스의 소멸자가 실행 완료되면 슈퍼 클래스의 소멸자가 자동으로 호출된다. 만약 서브 클래스에 소멸자가 따로 없더라도 슈퍼 클래스엔 소멸자가 있다면 자동으로 항상 호출된다.

인스턴스는 소멸자가 호출될 때까지는 할당 해제되지 않기 때문에 소멸자는 인스턴스의 모든 프로퍼티에 접근할 수 있고 수정도 가능하다.


Deinitializers in Action

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
    }
}

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)
    }
}

위의 코드로 소멸자의 동작에 대해 살펴보자. 위의 코드에서 Bank 클래스는 유통 중인 코인이 10000개를 넘을 수 없도록 관리한다. 그리고 coinsInBank는 현재 Bank 인스턴스에 존재하는 코인 수를 나타낸다. 이를 distribute(coins:), receive(coins:) 메서드를 통해 코인의 수를 수정한다. Player 클래스는 coinsInPurse 프로퍼티에 현재 플레이어가 가진 코인 수를 저장한다. 모든 플레이어가 가진 코인의 수가 10000개가 되어야 하기 때문에 만약 플레이어 인스턴스를 할당 해제한다면 해당 플레이어의 코인을 다시 Bank 인스턴스로 돌려줘야 한다. 이러한 부분을 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"

위의 코드처럼 100개의 코인을 가진 플레이어 1 인스턴스를 생성하면 Bank에는 9900개의 코인이 남아있게 된다.

 

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"

플레이어 1이 게임에서 이겨서 2000개의 코인을 받게 되면 플레이어 1의 지갑에는 2100개의 코인이 Bank인스턴스에는 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"

이때 플레이어1에 nil을 저장하면 메모리 할당이 해제되는데 이 때 Player 클래스의 소멸자가 실행되어 플레이어 1의 코인을 Bank인스턴스에 반환한다. 따라서 다시 Bank인스턴스에는 10000개의 코인이 존재하게 된다.

반응형
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함