Deinitialization デイニシャライズ

A deinitializer is called immediately before a class instance is deallocated. You write deinitializers with the deinit keyword, similar to how initializers are written with the init keyword. Deinitializers are only available on class types. デイニシャライザは、クラスインスタンスが割り当て解除される直前に呼ばれます。あなたは、イニシャライザがinitキーワードで書かれる方法と同様に、デイニシャライザをdeinitキーワードを使って書きます。デイニシャライザは、クラス型で利用可能なだけです。

How Deinitialization Works デイニシャライズはどのように働くか

Swift automatically deallocates your instances when they’re no longer needed, to free up resources. Swift handles the memory management of instances through automatic reference counting (ARC), as described in Automatic Reference Counting. Typically you don’t need to perform manual cleanup when your instances are deallocated. However, when you are working with your own resources, you might need to perform some additional cleanup yourself. For example, if you create a custom class to open a file and write some data to it, you might need to close the file before the class instance is deallocated. スウィフトは自動的に、それらがもはや必要とされない場合はあなたのインスタンスを割り当て解除して、資源を自由に使えるようにします。スウィフトは、自動参照カウントで記述されるように、インスタンスのメモリ管理を自動参照カウントARC)を通して取り扱います。概して、あなたのインスタンスが割り当て解除されるとき、あなたが手動で掃除をする必要がありません。しかし、あなたがあなた独自のリソース(計算資源)を扱うとき、あなたは追加のいくらかの掃除をあなた自身でする必要があるかもしれません。例えば、あなたがファイルを開いてそれに何かのデータを書くあつらえのクラスを作成するならば、クラスインスタンスが割り当て解除される前に、あなたはファイルを閉じる必要があるでしょう。

Class definitions can have at most one deinitializer per class. The deinitializer doesn’t take any parameters and is written without parentheses: クラス定義は、クラスごとに多くとも1つのデイニシャライザしか持つことができません。デイニシャライザは、まったくパラメータを取りません、したがって丸括弧なしで書かれます:

  1. deinit {
  2. // perform the deinitialization(デイニシャライズを実行する)
  3. }

Deinitializers are called automatically, just before instance deallocation takes place. You aren’t allowed to call a deinitializer yourself. Superclass deinitializers are inherited by their subclasses, and the superclass deinitializer is called automatically at the end of a subclass deinitializer implementation. Superclass deinitializers are always called, even if a subclass doesn’t provide its own deinitializer. デイニシャライザは、インスタンスの割り当て解除が起こる直前に、自動的に呼ばれます。あなたは、デイニシャライザをあなた自身で呼び出すことは許されません。スーパークラスのデイニシャライザは、それらのサブクラスそれらによって継承されます、そして、スーパークラスのデイニシャライザはサブクラスのデイニシャライザ実施の終わりに自動的に呼ばれます。スーパークラスのデイニシャライザは、たとえサブクラスがそれ自身のデイニシャライザを提供しないとしても、常に呼ばれます。

Because an instance isn’t deallocated until after its deinitializer is called, a deinitializer can access all properties of the instance it’s called on and can modify its behavior based on those properties (such as looking up the name of a file that needs to be closed). インスタンスはそれのデイニシャライザが呼ばれる後までは割り当て解除されないので、デイニシャライザはそれが呼ばれるところのインスタンスの全てのプロパティにアクセスすることができて、それらのプロパティに基づいてその挙動を修正することができます(たとえば閉じられる必要があるファイルの名前を調べることなど)。

Deinitializers in Action デイニシャライザの動作

Here’s an example of a deinitializer in action. This example defines two new types, Bank and Player, for a simple game. The Bank class manages a made-up currency, which can never have more than 10,000 coins in circulation. There can only ever be one Bank in the game, and so the Bank is implemented as a class with type properties and methods to store and manage its current state: デイニシャライザの動作の例は、ここにあります。この例は、2つの新しい型BankPlayerを、単純なゲームのために定義します。Bankクラスは、ある架空の通貨を管理します、そしてそれは、流通する10,000個以上のコインを決して持つことができません。1つのBankだけがゲームにおいて存在することができます、なのでBankは型プロパティと型メソッドをもつクラスとして実装されて、その現在の状態を格納および管理します:

  1. class Bank {
  2. static var coinsInBank = 10_000
  3. static func distribute(coins numberOfCoinsRequested: Int) -> Int {
  4. let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank)
  5. coinsInBank -= numberOfCoinsToVend
  6. return numberOfCoinsToVend
  7. }
  8. static func receive(coins: Int) {
  9. coinsInBank += coins
  10. }
  11. }

Bank keeps track of the current number of coins it holds with its coinsInBank property. It also offers two methods—distribute(coins:) and receive(coins:)—to handle the distribution and collection of coins. Bankは、それがそのcoinsInBankプロパティで保持するコインの現在の数の情報を得続けます。それはまた、2つのメソッド ― distribute(coins:)receive(coins:)— ― を提供して、コインの配布と回収を取り扱います。

The distribute(coins:) method checks that there are enough coins in the bank before distributing them. If there aren’t enough coins, Bank returns a smaller number than the number that was requested (and returns zero if no coins are left in the bank). It returns an integer value to indicate the actual number of coins that were provided. distribute(coins:)メソッドは、十分なコインがそれらを配布する前に胴元にあることを確認します。十分なコインがないならば、Bankは要請された数より少ない数を返します(そしてコインが胴元に残っていないならばゼロを返します)。それは、提供されたコインの実際の数を示す整数値を返します。

The receive(coins:) method simply adds the received number of coins back into the bank’s coin store. receive(coins:)メソッドは、単純に受け取ったコインの数を胴元のコインの蓄えに戻すよう加えます。

The Player class describes a player in the game. Each player has a certain number of coins stored in their purse at any time. This is represented by the player’s coinsInPurse property: Playerクラスは、ゲームにおけるプレーヤーを記述します。各々のプレーヤーは、特定の数のコインをいつでもかれらの財布に保管しておきます。これは、プレーヤーのcoinsInPurseプロパティによって表されます:

  1. class Player {
  2. var coinsInPurse: Int
  3. init(coins: Int) {
  4. coinsInPurse = Bank.distribute(coins: coins)
  5. }
  6. func win(coins: Int) {
  7. coinsInPurse += Bank.distribute(coins: coins)
  8. }
  9. deinit {
  10. Bank.receive(coins: coinsInPurse)
  11. }
  12. }

Each Player instance is initialized with a starting allowance of a specified number of coins from the bank during initialization, although a Player instance may receive fewer than that number if not enough coins are available. Playerインスタンスは、初期化の間に、胴元からの指定された数のコインの開始手当で初期化されます、とは言え、十分なコインが利用可能でなければPlayerインスタンスはその数より少ないものを受け取るかもしれません。

The Player class defines a win(coins:) method, which retrieves a certain number of coins from the bank and adds them to the player’s purse. The Player class also implements a deinitializer, which is called just before a Player instance is deallocated. Here, the deinitializer simply returns all of the player’s coins to the bank: Playerクラスはwin(coins:)メソッドを定義します、それは、胴元からコインの特定の数を取り戻して、それらをプレーヤーの財布に加えます。Playerクラスはまた、デイニシャライザを実装します、それはPlayerインスタンスが割り当て解除される直前に呼ばれます。ここでは、デイニシャライザは単に胴元にプレーヤーのコインの全てを返します:

  1. var playerOne: Player? = Player(coins: 100)
  2. print("A new player has joined the game with \(playerOne!.coinsInPurse) coins")
  3. // Prints "A new player has joined the game with 100 coins"(「新しいプレーヤーが、100のコインを持ってゲームに参加しました」を出力します)
  4. print("There are now \(Bank.coinsInBank) coins left in the bank")
  5. // Prints "There are now 9900 coins left in the bank"(「現在9900個のコインが胴元に残されます」を出力します)

A new Player instance is created, with a request for 100 coins if they’re available. This Player instance is stored in an optional Player variable called playerOne. An optional variable is used here, because players can leave the game at any point. The optional lets you track whether there’s currently a player in the game. 新しいPlayerインスタンスが、それが可能ならば100のコインを要請して作成されます。このPlayerインスタンスは、playerOneと呼ばれるオプショナルのPlayer変数に格納されます。オプショナルの変数がここで使われます、なぜなら、プレーヤーはどの時点でもゲームから離れることができるからです。オプショナルは、プレーヤーが現在ゲーム中かどうかあなたに追跡させます。

Because playerOne is an optional, it’s qualified with an exclamation point (!) when its coinsInPurse property is accessed to print its default number of coins, and whenever its win(coins:) method is called: playerOneがオプショナルであることから、それは感嘆符(!)で修飾されます、それのもつcoinsInPurseプロパティがその省略時のコイン数を出力するためにアクセスされる時に、そして何時でもそれのwin(coins:)メソッドが呼ばれる時に:

  1. playerOne!.win(coins: 2_000)
  2. print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins")
  3. // Prints "PlayerOne won 2000 coins & now has 2100 coins"(「PlayerOneは2000のコインを獲得&現在2100のコインを持ちます」を出力します)
  4. print("The bank now only has \(Bank.coinsInBank) coins left")
  5. // Prints "The bank now only has 7900 coins left"(「胴元には現在7900個のコインだけが残っています」を出力します)

Here, the player has won 2,000 coins. The player’s purse now contains 2,100 coins, and the bank has only 7,900 coins left. ここでは、プレーヤーは2,000個のコインを獲得しました。プレーヤーの財布は現在2,100個のコインを含みます、そして、胴元は7,900個のコインだけが残っています。

  1. playerOne = nil
  2. print("PlayerOne has left the game")
  3. // Prints "PlayerOne has left the game"(「PlayerOneは、ゲームを離れました」を出力します)
  4. print("The bank now has \(Bank.coinsInBank) coins")
  5. // Prints "The bank now has 10000 coins"(「胴元には現在10000コインがあります」を出力します)

The player has now left the game. This is indicated by setting the optional playerOne variable to nil, meaning “no Player instance.” At the point that this happens, the playerOne variable’s reference to the Player instance is broken. No other properties or variables are still referring to the Player instance, and so it’s deallocated in order to free up its memory. Just before this happens, its deinitializer is called automatically, and its coins are returned to the bank. プレーヤーは、現在ゲームから離れました。これはオプショナルのplayerOne変数に、「Playerインスタンスがない」ことを意味する、nilを設定することによって示されます。これが起こる時点で、playerOne変数のもつPlayerインスタンスへの参照は壊れています。他のいかなるプロパティまたは変数も、もはやPlayerインスタンスに言及していません、なのでそれは、それのもつメモリを開放するために順次割り当て解除されます。これが起こる直前に、そのデイニシャライザは自動的に呼ばれます、そしてそのコインは胴元に返されます。

Initialization 初期化

Optional Chaining オプショナル連鎖