woshidan's blog

あいとゆうきとITと、とっておきの話。

はてな教科書の「プログラミング言語 Swift」を読んでます 5

https://github.com/hatena/Hatena-Textbook/blob/master/swift-programming-language.md

イニシャライザが難しかったのですが、のんびり読んでいきます。

Inheritance

class名の右に:をつけてスーパークラスを指定することでそのクラスを継承することができます。

スーパークラスの実装を明示的に利用する場合は、superキーワードを用います。

  1> class Man { 
  2.     func greeting() -> String { 
  3.         return "Hello" 
  4.     } 
  5. } 
  6> class Student : Man { 
  7.     override func greeting() -> String { 
  8.         return "\(super.greeting()), Teacher" 
  9.     } 
 10.     } 
 11> let taro: Man = Student()
taro: Student = {
  __lldb_expr_1.Man = {}
}
 12> taro.greeting()
$R0: String = "Hello, Teacher"

finalキーワードをclassfuncにつけることで継承を制限することができます。

Initializers and deinitializers

Initializers

  • class, enum, structではイニシャライザが定義できる
  • イニシャライザでは、Optional型ではないstoredプロパティ(let, varをつけるいわゆる普通のインスタンス変数ないしクラス変数)で、初期値が設定されていないものをすべて初期化する必要がある
  • イニシャライザは複数定義可能で、メソッドとは異なり第一引数からラベルを明記する
    • 型が同じでもラベルによってイニシャライザが区別される
  • 下記の条件で、class はデフォルトで空のイニシャライザを持つ
    • イニシャライザが一つも定義されておらず
    • かつイニシャライザで初期化するべき stored プロパティが存在しない
  • 下記の条件で、 structは全ての初期化すべき stored プロパティを定義順に指定するデフォルトのイニシャライザを持つ
    • イニシャライザが一つも定義されていない場合

値型のイニシャライザ

http://qiita.com/cotrpepe/items/3052d91468f1b852582a http://qiita.com/qoAop/items/a28e3649feaf38af1134

// 参考: http://qiita.com/_mpon/items/4491d19fa50b2039af35

 18> enum Size { 
 19.     case Small, Medium, Large 
 20.  
 21.     // 引数なしコンストラクタ 
 22.     init() { 
 23.         self = .Small // デフォルト値の設定など
 24.     } 
 25. }
 26> Size()
$R3: Size = Small
// 値型の場合は self.init で自身のイニシャライザを呼び出すことができるのenumのそれがわからない..。
 27> enum Size { 
 28.     case Small, Medium, Large 
 29.  
 30.     // 引数なしコンストラクタ 
 31.     init() { 
 32.         self = .Small 
 33.     } 
 34.     init(type: Int) { 
 35.         if type % 3 == 0 { 
 36.             self = .Medium 
 37.         } else { 
 38.             self = self.init 
 39.         } 
 40.     } 
 41. } 
repl.swift:38:25: error: cannot assign value of type '_ -> _' to type 'Size'
            self = self.init
                   ~~~~~^~~~
// Structの場合は https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html より
  1> struct Size { 
  2.     var width = 0.0, height = 0.0 
  3. } 
  4. struct Point { 
  5.     var x = 0.0, y = 0.0 
  6. }
  7>  
  8> struct Rect { 
  9.     var origin = Point() 
 10.     var size = Size() 
 11.     init() {} 
 12.     init(origin: Point, size: Size) { 
 13.         self.origin = origin 
 14.         self.size = size 
 15.     } 
 16.     init(center: Point, size: Size) { 
 17.         let originX = center.x - (size.width / 2) 
 18.         let originY = center.y - (size.height / 2) 
 19.         self.init(origin: Point(x: originX, y: originY), size: size) 
 20.     } 
 21. }

参照型のイニシャライザ

  • designated イニシャライザはclass中の初期値が与えられていないletやvarのstoredプロパティの値をすべて定義する
  • ほかのイニシャライザには convenience修飾子をつける
    • convenienceイニシャライザはdesignated イニシャライザを呼び出さなければいけない
  • クラスを継承している場合は、必ずsuperclassのイニシャライザを呼び出さなければいけない
    • 基本的には、サブクラスはスーパークラスのイニシャライザを継承しない。
    • スーパークラスの designated イニシャライザと同様のイニシャライザを定義する場合、override 修飾子が必要
    • サブクラスが designated イニシャライザを定義していない場合、スーパークラスの designated イニシャライザが利用できる
    • required 修飾子をイニシャライザに前置することで、サブクラスにそのイニシャライザの実装を強制することができる
 42> class Initial { 
 43.     var name: String 
 44.     init() { 
 45.         name = "Sample" 
 46.     } 
 47.      
 48.    convenience init(initName: String) { 
 49.        self.init() 
 50.        self.name = initName 
 51.     } 
 52.     func display() { 
 53.         print(name.substringToIndex(name.startIndex.advancedBy(1)))
 54.     } 
 55. } 
 56> Initial().display()
S
 57> Initial(initName: "Example").display() 
E

SubクラスがSuperクラスのdesignated イニシャライザを定義していない場合、スーパークラスの designated イニシャライザが利用できます。

 27> class Super { 
 28.     init() { 
 29.         print("Super")
 30.     } 
 31. } 
 32> class Sub : Super {} 
 33> Sub() 
Super
$R1: Sub = {
  __lldb_expr_11.Super = {}
}

required 修飾子で実装を強制することもできます。

 34> class Super { 
 35.     init() { 
 36.         print("Super") 
 37.     } 
 38.     required convenience init(printString: String) { 
 39.         self.init()
 40.         print(printString) 
 41.     } 
 42. } 
 43> class Sub : Super {} 
 44> Sub()
Super
$R2: Sub = {
  __lldb_expr_19.Super = {}
}
 45> Sub(printString: "Test")
Super
Test
$R3: Sub = {
  __lldb_expr_19.Super = {}
}

Failable Initializers

  • init??をつけたイニシャライザは与えられた引数によっては初期化を失敗させてnilを返すようにできる
  • そのイニシャライザの返り値をしては、Optionalとなる

Deinitializers

クラスのインスタンスが破棄されるときに実行したい処理はデイニシャライザ(deinit {...})にて定義できる。