Initialization

訳はてきとう

前回に引き続き https://docs.swift.org/swift-book/LanguageGuide/Initialization.html を読む。

  • 格納型プロパティは、初期化子のなかで値を設定するか、プロパティの宣言に初期値を書く
  • 初期化子の中で値を設定するか、初期値を宣言したときは、プロパティオブザーバは呼び出されない
  • プロパティがいつも同じ初期値をとるなら、初期化子内で設定するよりも初期値を与えよ
  • クラスの格納型プロパティにすべて初期値があればデフォルト初期化子がある
  • 構造体には全項目初期化子がある
  • 初期化子の委譲は self.init
  • 指定初期化子と便利初期化子
  • クラスの指定初期化子は、少ない傾向。ひとつしか持たないことがよくある
  • どのクラスも1つは指定初期化子を持たなければならない
  • 便利初期化子 convenience 修飾子を init キーワードの前につけて
  • 委譲のルール
    1. 指定初期化子は、スーパークラスの指定初期化子を呼び出さなければならない
    2. 便利初期化子は、同じクラスの他の初期化子を呼び出さなければならない
    3. 便利初期化子は、最終的には指定初期化子を呼び出さなければならない
  • 単純版
    1. 指定初期化子は上へ委譲する
    2. 便利初期化子は横へ委譲する
  • Swiftでは、クラスの初期化は2段階
  • 2段階初期化プロセスを使用すると、クラス階層内の各クラスに完全な柔軟性を与えながら、初期化を安全に行うことができる
  • 2段階初期化は、プロパティ値が初期化される前にアクセスされるのを防ぎ、予期せず別の初期化子によってプロパティ値が別の値に設定されるのを防ぐ
  • 安全性検査
    1. 指定初期化子は、スーパークラスの初期化子に委譲する前に、そのクラスによって導入されたすべてのプロパティが初期化されていることを保証する必要がある
    2. 指定初期化子は、継承されたプロパティに値を割り当てる前に、スーパークラスの初期化子に委譲する必要がある
    3. 便利初期化子は、プロパティ(同じクラスで定義されたプロパティを含む)に値を割り当てる前に、別の初期化子に委譲する必要がある
    4. 初期化子は、初期化の第1段階が完了するまで、インスタンスメソッドを呼び出したり、インスタンスプロパティの値を読み込んだり、selfを値として参照したりすることはできない
  • 2つの段階
    • 第1段階
      • クラスの初期化子が呼び出される
      • 新しいインスタンスのためのメモリが確保される(未だ初期化されてない)
      • 指定初期化子がクラスのプロパティに値が格納されるのを確実にする(このクラスのプロパティは初期化済み)
      • スーパークラスの初期化子へ、継承チェインの先頭まで
      • 継承チェインの先頭まで来たら、全部の格納プロパティに値が入ってメモリは初期化済み(第1段階終了)
    • 第2段階
      • 継承チェインの先頭から戻りながら、指定初期化子にはさらにカスタマイズする選択肢がある
      • 初期化子は、この段階では、selfにアクセスしたりプロパティ値を変更したり、メソッドを呼んだりできる
      • 最後に、便利初期化子にはカスタマイズする選択肢がある
  • Objective-Cのサブクラスとは異なり、Swiftサブクラスはデフォルトでスーパークラス初期化子を継承しない
  • 自動的に継承される初期化子。サブクラスで提供するプロパティにすべて初期値が宣言されているとして、
    • ルール1 サブクラスで指定初期化子を何も定義しないなら、スーパークラスの指定初期化子をすべて継承する
    • ルール2 サブクラスがそのスーパークラスの指定初期化子をすべて継承しているなら、スーパークラスの便利初期化子をすべて継承する
  • 失敗可能初期化子 init?
  • 失敗時はnilreturnするけど、成功時はとくになにもreturnしないよ
  • 同じ名前と型のパラメータで失敗可能・失敗不能初期化子を両方定義することはできない
  • rawValueのあるenumは自動的に init?(rawValue:) を収容している
  • 失敗可能を失敗不能にオーバーライドできるけど、逆は無理
  • 初期化中に強制アンラップしている失敗可能な初期化子は init!
  • サブクラスで実装しなければならない初期化子は required init()
  • クロージャでプロパティの初期化 let someProperty: SomeType = { return someValue }()

やたら量が多いので、他の章の5倍はあるけど、内容はまあ、ゾッともゲッともしない。ああそうだね、という感じ。 スーパークラスの初期化が終わってないのにスーパークラスのメソッドが呼び出せたりするような危険な状況を回避するために、 厳格で単純なルールを作っている、…と思った(夏休みの感想)。