[Swift] Deinitialization

상 원·2022년 7월 23일
0

Swift

목록 보기
26/31
post-thumbnail

Deinitializer는 클래스 인스턴스가 deallocate될 때 즉시 실행된다.
deinit 키워드를 붙여서 쓰고, 클래스에서만 쓸 수 있음!!

How Deinitialization Works

Swift는 인스턴스가 더 이상 사용되지 않는다고 판단되면 리소스를 반환해주기 위해 인스턴스를 deallocate한다.
보통은 직접 cleanup을 하지 않아도 되지만, 내 리소스를 사용할 때는 cleanup을 해줘야 할 때도 있음.

예를 들어 커스텀 클래스를 만들어서 파일을 열고 데이터를 집어넣는 데 쓴다면, 클래스 인스턴스가 deallocate되기 전에 파일을 닫아야 한다.

deinit은 매개변수를 가지지 않고, 클래스마다 최대 한 개만 가질 수 있음.

deinit {
    // perform the deinitialization
}

얘네는 instance deallocation이 되기 직전에 자동으로 호출되고, 내가 직접 호출하는 건 불가능함.

슈퍼클래스의 디이셜라이저는 서브클래스에 상속되고, 서브클래스 디이니셜라이저가 끝난 후 실행된다. 서브클래스 디이니셜라이저가 없더라도 슈퍼클래스의 디이니셜라이저는 항상 실행됨.

당연히 디이니셜라이저가 끝난 후 인스턴스가 deallocate되기 때문에, 디이니셜라이저는 인스턴스의 모든 프로퍼티에 접근 가능함! 닫을 파일의 이름을 알아본다던가..

Deinitializers in Action

예제를 통해 아라보자.
간단한 게임임!
10,000코인 이상 가질 수 없는 Bank 클래스와 Player 클래스가 있음.
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:) 메소드는 요청된 코인의 갯수와 잔액을 비교해서 요청된 게 잔액보다 많다면 잔액을 반환하고, 적다면 요청된 만큼을 반환하고, 아예 없다면 0을 반환한다. 반환값(출금액)은 numberOfCoinsToVend 에 저장돼서 반환됨!

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

플레이어마다 초기화 때 은행에서 코인을 지급받는데(distribute), 코인이 부족하면 초기화 때 써넣은 갯수보다 적게 받을수도 있음.

win(coins:) 메소드는 플레이어의 지갑에 돈을 더 넣어줌. 상금개념인듯?

디이니셜라이저는 모든 플레이어의 돈을 은행에 다시 돌려줌!

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코인을 받는다. 옵셔널로 지정한 이유는 플레이어가 언제든 게임을 떠날 수 있기 때문! 요걸로 플레이어가 게임을 플레이하고 있는지 아닌지를 판단할 수 있다.

playerOne 이 옵셔널이기 때문에 사용할 때도 언래핑을 위해서 ! 를 붙여줘야 함!

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코인을 땄을 때 플레이어의 잔액과 은행의 잔액을 위와 같이 확인할 수 있음.

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"

플레이어가 게임을 떠나면 nil로 만들어지는데, playerOnePlayer 클래스 인스턴스의 참조가 사라지는 거!
다른 프로퍼티나 변수가 Player 를 참조하고 있지 않으므로, 인스턴스가 deallocate 됨.
그래서 디이니셜라이저가 실행되고 은행으로 코인이 모두 돌아가는 것!

profile
ios developer

0개의 댓글