デイニシャライザは、クラスインスタンスの割り当てが解除される直前に呼び出されます。deinit
キーワードを使用してイニシャライザinitを作成する方法と同様に、キーワードを使用してデイニシャライザを作成します。デイニシャライザは、クラスタイプでのみ使用できます。
デイニシャライズのしくみ
Swiftは、インスタンスが不要になったときに自動的に割り当てを解除して、リソースを解放します。Swiftは自動参照カウントを通じてインスタンスのメモリ管理を処理する自動参照カウント。通常、インスタンスの割り当てが解除されたときに手動でクリーンアップを実行する必要はありません。ただし、独自のリソースを使用している場合は、追加のクリーンアップを自分で実行する必要がある場合があります。たとえば、ファイルを開いてデータを書き込むカスタムクラスを作成する場合、クラスインスタンスの割り当てを解除する前にファイルを閉じる必要がある場合があります。
クラス定義は、クラスごとに最大1つの初期化子を持つことができます。デイニシャライザはパラメータを取らず、括弧なしで記述されます。
deinit { // perform the deinitialization }
デイニシャライザは、インスタンスの割り当て解除が行われる直前に自動的に呼び出されます。自分でデイニシャライザを呼び出すことはできません。スーパークラスのデイニシャライザはサブクラスによって継承され、スーパークラスのデイニシャライザはサブクラスのデイニシャライザの実装の最後に自動的に呼び出されます。サブクラスが独自のデイニシャライザを提供しない場合でも、スーパークラスのデイニシャライザは常に呼び出されます。
インスタンスはデイニシャライザが呼び出されるまで割り当て解除されないため、デイニシャライザは呼び出されたインスタンスのすべてのプロパティにアクセスでき、それらのプロパティに基づいて動作を変更できます(閉じる必要のあるファイルの名前の検索など) )。
実行中のデイニシャライザ
動作中のデイニシャライザの例を次に示します。この例では、単純なゲーム用に2つの新しいタイプ、BankとPlayerを定義しています。このBank
クラスは、1万枚を超えるコインを流通させることのできない構成通貨を管理します。ゲームにはBankは1つしか存在できないため、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
プロパティで保持しているコインの現在の数を追跡します。また、コインの配布・回収を扱う 2つのメソッド distribute(coins:)とreceive(coins:)を提供します。
このdistribute(coins:)
メソッドは、銀行に十分な量のコインがあることを確認してから、配布します。十分なコインがない場合、Bank
は要求された数よりも小さい数を返します(銀行にコインが残っていない場合はゼロを返します)。提供されたコインの実際の数を示す整数値を返します。
このreceive(coins:)
メソッドは、受け取った数のコインをBankのコインストアに追加します。
この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:)メソッドを定義し、Bankからコインの特定の数を取得し、遊技者の財布にそれらを追加します。Player
クラスには、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"
新しいPlayer
インスタンスが作成され、利用可能な場合は100コインがリクエストされます。このPlayer
インスタンスは、playerOneというオプションの変数に格納されます。プレーヤーはいつでもゲームを離れることができるため、ここではオプションの変数が使用されています。オプションを使用すると、現在ゲームにプレーヤーがいるかどうかを追跡できます。
playerOne
はオプションであるため、そのcoinsInPurse
プロパティにアクセスしてデフォルトのコイン数を出力するとき、およびそのwin(coins:)
メソッドが呼び出されるときは常に、感嘆符(!)で修飾されます。
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"
- 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”
プレイヤーはゲームを離れました。これは、オプションのplayerOne
変数を「Player
インスタンスなし」を意味するnilに設定することで示されます。これが発生した時点で、playerOne
変数へのPlayer
インスタンスへの参照は壊れています。他のプロパティや変数はまだPlayer
インスタンスを参照していないため、メモリを解放するために割り当てが解除されます。これが発生する直前に、そのデイニシャライザが自動的に呼び出され、そのコインが銀行に返されます。