[Swift] Deinitialization

LEEHAKJIN-VV·2022년 5월 22일
0

Study-Swift 5.6

목록 보기
17/22

참고사이트:
English: The swift programming language
Korean: The swift programming language


Deinitialization (초기화 해지)

Deinitalizer(디이니셜라이저)는 클래스 인스턴스가 소멸될 때 즉시 호출된다. 구현 방법은 이니셜라이저와 유사하게 deinit 키워드를 사용한다. deinitalizer는 오직 클래스 타입에서 사용된다.

How Deinitialization Works (초기화 해지 동작)

Swift는 인스턴스가 더 이상 사용되지 않을 때 메모리 확보를 위해 자동으로 할당된 자원을 해제한다. Swift는 ARC(automatic reference counting)로 인스턴스의 메모리를 관리한다. 일반적으로 인스턴스의 소멸을 수동으로 작업할 필요가 없다. 그러나 자체 자원을 작업하는 경우 몇 가지 예외가 있다. 예를 들어 파일 읽기 쓰기를 위해 custom 클래스를 생성하는 경우 클래스 인스턴스의 자원을 해지하기 전에 파일을 닫아야 한다.

클래스 당 1개의 deinitalizer를 가진다. deinitalizer는 파라미터와 괄호 없이 구현한다.

deinit {
    // perform the deinitialization
}

deinitalizer는 인스턴스의 할당 해제가 일어나기 직전에 자동으로 호출되며, 수동으로 호출할 수 없다. 슈퍼클래스의 deinitalizer는 서브클래스에서 자동으로 상속되고, 서브클래스의 deinitalizer가 선언되지 않아도 자동으로 호출된다. 이유는 인스턴스의 자원은 deinitalizer가 호출되기 전까지 해지되지 않기 때문이다.

Deinitializers in Action (초기화 해지 사용)

deinitalizer 사용의 예제를 살펴보겠다. 이 예제는 간단한 게임을 위해 2개의 새로운 클래스 Bank, Player를 선언한다. Bank클래스는 10,000개 이상의 코인을 유통할 수 없는 통화정책을 가진다. 게임에서는 Bank가 오직 1개만 존재해야 하므로 타입 프로퍼티와 타입 메소드로 구현되었다.

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 프로퍼티는 은행이 현재 보유중인 코인의 수를 의미한다. 또한 2개의 타입 메소드 distribute(coins:), receive(coins:)를 가지고 이는 통화의 유통을 다룬다.

distribute(coins:) 메소드는 코인을 분배하는 역할을 담당하며, 분배하는 코인의 수가 최대 10,000을 넘지 않도록 유지하며 분배 요청이 들어온 코인의 수가 현재 은행에 보유 중인 코인의 수보다 많다면 현재 보유 중인 코인을 모두 반환한다. 반환 값은 정수형이다.

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 클래스는 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"

Plyaer의 인스턴스는 100개의 코인을 가지고 생성된다. 이 인스턴스는 optional 타입의 playerOne 프로퍼티에 저장된다. 프로퍼티를 optional 타입으로 정의한 이유는 플레이어가 언제든지 게임을 떠날 수 있기 때문이다. 즉 플레이어의 게임 참여 여부는 프로퍼티가 nil 인지 아닌지로 결정한다.

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"

사용자가 게임에서 이겨 2,000코인을 얻었다. 이제 플레이어는 2,100코인을 보유하고 있고 은행은 7,900코인을 보유하고 있다.

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을 할당하였다. 이는 플레이어가 게임을 떠난 것을 의미한다. 이 시점에서 Player 인스턴스에 대한 변수 playerOne의 참조가 깨졌다, 그러므로 메모리 확보를 위해 할당이 해제된다. 할당이 해제되기 직전, deinitializer가 자동으로 호출되고 은행에 플레이어가 보유한 코인을 반납하게 된다.

0개의 댓글