忘備録-Swiftのクラス

趣味でIOSアプリ開発をかじっていた自分が、改めてSwiftを勉強し始めた際に、曖昧に理解していたところや知らなかったところをメモしています。いつか書き直します。

## 参考文献

この記事は以下の書籍の情報を参考にして執筆しました。

- [詳解 Swift 第5版](https://www.amazon.co.jp/%E8%A9%B3%E8%A7%A3Swift-%E7%AC%AC5%E7%89%88-%E8%8D%BB%E5%8E%9F-%E5%89%9B%E5%BF%97/dp/481560407X)

##クラスの概要

クラスのインスタンスは参照型。
インスタンスを変数に代入したり、メソッドの引数として渡される場合、コピーを渡すのではなく参照を渡す。

アプリケーションプログラミングでは、インスタンス同士を柔軟に結びつけ、ソフトウェアの機能を実現させるために、動的結合やポリモーフィズムの機能を備えた参照型のデータ型であるクラスが必要。

クラス定義は実装を隠して独立性を他高めることを目的としている。
プロパティが全て公開されていることが前提の全項目イニシャライザは使えない。

イニシャライザがないなら「クラス()」という記法、規定イニシャライザは使える。

##継承

継承 : 別のクラスを利用して同様な記述を繰り返すことなく新しいクラスを定義できる仕組み。

サブクラス : 定義を引き継いで新たに定義されるクラス。
スーパークラス : 参照される側。
ベースクラス : スーパークラスを指定せずに定義するクラス。

オーバーライド : スーパークラスを上書きする操作
サブクラスで自信の定義を示すのが「self」スーパークラスの定義を示すのが「super」

####必須イニシャライザ

スーパークラスにもサブクラスにも確実にイニシャライザが必要な場合に、必ず実装しなければならないことを示すイニシャライザ。
イニシャライザの前にrequiredという修飾子を置くことで定義する。
クラスから継承してイニシャライザを新しく増やしていない場合はその限りではない。

####クラスメソッド、クラスプロパティ

クラスプロパティ : class記述から始まるプロパティ。計算型に限定される。
クラスメソッド :  class記述から始まるメソッド。
これらはタイプメソッド、タイププロパティと同様にそのクラス自身の属性として利用できる。
違いはクラスメソッドなどはサブクラスで定義の上書きができる。



```swift
class Animal: CustomStringConvertible{
  var weight: Int
  class var className: String {"Animal"}

  required init(w: Int){    //必須イニシャライザ
    weight = w
  }

  var description: String{
    Self.className
  }

  func cry(s:String){
    print(s)
  }

  class func translation() {
    print("動物")
  }
}

class Dog: Animal {
  var name: String = ""

  override class var className: String {"Dog"}

  required init(w: Int) {    // 他にもイニシャライザを定義したので、この節の記述がないとエラーになる。
    super.init(w: w)
  }
  
  init(w: Int, n: String) {
    super.init(w: w)
    self.name = n
  }

  override var description: String{
    if name == "" {
      return Self.className
    } else {
      return "\(name)"
    }
  }

  override class func translation() {
    print("犬")
  }
}


let pochi = Dog(w: 5)
print(pochi)
pochi.name = "pochi"
print(pochi)
// 関数が継承されているので使える
pochi.cry(s: "wan")    // wan

print(Animal.className)    // Animal
Animal.translation()    // 動物

print(Dog.className)    // Dog
Dog.translation()    // 犬

```

##初期化の手順
指定イニシャライザ : 使うと初期化が完了する。init~
簡易イニシャライザ : 他のイニシャライザの助けを借りて初期化する。convenience init~



1.サブクラスのイニシャライザ呼び出し。簡易イニシャライザなら必要な前処理を行なって指定イニシャライザを呼び出す。
2.サブクラスで追加された変数・定数の初期化
3.スーパークラスのイニシャライザ呼び出し。2.3を繰り返す。
4.ベースクラスのイニシャライザ呼び出し、初期化。
5.サブクラスのイニシャライザがスーパークラスで初期化された変数について変更を加える。この時点でメソッド各種プロパティにアクセス可。
6.サブクラスのイニシャライザが次々に5を実施し最初の指定イニシャライザ、簡易イニシャライザの実行が終了して初期化が終わる。

##メタタイプとダイナミックタイプ
ダイナミックタイプ : インスタンスの型を表すオジェクトを値として得ることができる。Type(of:)で取得できる。
メタタイプ : A.self記述でAのダイナミックタイプが取得でき、このダイナミックタイプが持っているA.Typeと書き表される型。
メタタイプとダイナミックタイプの関係は、型名とインスタンスの関係。

```swift

class Animal: CustomStringConvertible{
  var weight: Int
  class var className: String {"Animal"}

  required init(w: Int){    //必須イニシャライザ
    weight = w
  }

  var description: String{
    Self.className
  }

  func cry(s:String){
    print(s)
  }

  class func translation() {
    print("動物")
  }
}

class Dog: Animal {
  var name: String = ""

  override class var className: String {"Dog"}

  override var description: String{
    if name == "" {
      return Self.className
    } else {
      return "\(name)"
    }
  }

  override class func translation() {
    print("犬")
  }
}


let pochi = Dog(w: 5)
print(type(of:pochi) == Dog.self)    // true
print(type(of:pochi) == Animal.self)    // false
```

##解放処理とデイニシャライザ

解放処理 : ファイルのクローズや作業メモリの解放などを行う処理
デイニシャライザ : インスタンスが解放される直前に呼び出される。deinit{ 処理 }と記述する。