初期化


初期化 は、使用するためのクラス、構造体、または列挙型のインスタンスを準備する手順です。この手順には、そのインスタンスに格納された各プロパティの初期値を設定し、新しいインスタンスを使用する準備ができる前に必要とされる全ての他の設定や初期化を含みます。


特定の型の新しいインスタンスを作成するために呼び出される特殊なメソッドのようなもので定義するのが イニシャライザ で、この初期化の手順を実装して下さい。Objective-C のイニシャライザとは異なり、Swift のイニシャライザは値を返しません。それらの主な役割は、それらが最初に使用される前に型の新しいインスタンスが正しく初期化されていることを保証することです。


クラス型のインスタンスは、デイニシャライザ を実装する事もでき、それはそのクラスのインスタンスが割り当て解除される直前に全てのカスタムクリーンアップを実行します。デイニシャライザの詳細については、デイニシャライザ を参照してください。



格納されたプロパティの初期値を設定


クラスと構造体は、そのクラスまたは構造体のインスタンスが作成される時までに、適切な初期値に、それらすべての格納されたプロパティを設定 しなければなりません。格納されたプロパティは、不確定な状態のままにすることはできません。


イニシャライザ内に格納されたプロパティの、またはプロパティの定義の一部としてデフォルトのプロパティ値を代入することによって、初期値を設定できます。これらのアクションは、以下のセクションで説明します。


注意: 格納されたプロパティにデフォルト値を代入し、またはイニシャライザ内でその初期値を設定すると、そのプロパティ値は、どのプロパティ監視者も呼び出すことなく、直接設定されます。


イニシャライザ


イニシャライザ は、特定の型の新しいインスタンスを作成するために呼美出されます。最も単純な形式では、イニシャライザは、init キーワードを使用して書かれた、パラメータなしのインスタンスメソッドのようになります:


  1. init() {
  2.         // perform some initialization here
  3. }


以下の例は、華氏 (Fahrenheit) のスケールで表した温度を格納するための Fahrenheit と言う新しい構造体を定義しています。Fahrenheit 構造体は、格納されたプロパティの、 Double 型である temperature を一つ持っています。


  1. struct Fahrenheit {
  2.         var temperature: Double
  3.         init() {
  4.                 temperature = 32.0
  5.         }
  6. }
  7. var f = Fahrenheit()
  8. print("The default temperature is \(f.temperature)° Fahrenheit")
  9. // prints "The default temperature is 32.0° Fahrenheit"


構造体は、パラメータなしの init の、一つのイニシャライザを定義しており、これは 32.0 の値 (華氏で表現された水の氷点) の格納された温度で初期化しています。



デフォルトのプロパティ値


上に示したように、イニシャライザ内から格納されたプロパティの初期値を設定できます。また、プロパティの宣言の一部として、デフォルトのプロパティ値 を指定できます。それが定義されていると、プロパティに初期値を代入することによって、デフォルトのプロパティ値を指定できます。



注意: プロパティが常に同じ初期値を取る場合、イニシャライザ内の値を設定するのではなく、デフォルト値を提供して下さい。最終結果は同じですが、デフォルト値はその宣言により密接に、プロパティの初期化を結び付けます。それはイニシャライザをより短く、明確にし、そのデフォルト値からプロパティの型を推論することができます。デフォルトのイニシャライザと、イニシャライザの継承の利点を活用するためには、この章で後述するように、デフォルト値もそれを容易にします。


temperature プロパティが宣言された時点で、そのプロパティのデフォルト値を提供することで、より簡単な形で上記の例からの** Fahrenheit 構造体を書くことができます。


  1. struct Fahrenheit {
  2.        var temperature = 32.0
  3. }


初期化のカスタマイズ


以下のセクションで説明するように、入力パラメータと optional のプロパティ型で、または初期化中に定数プロパティを代入することで、初期化プロセスをカスタマイズできます。



初期化パラメータ


型と、初期化プロセスをカスタマイズする値の名前を定義するために、イニシャライザの定義の一部として、初期化パラメータ を提供できます。初期化パラメータは、関数やメソッドのパラメータと同じ機能と構文を持っています。


以下の例は、摂氏 (Celsius) で表した温度を格納する、Celsius と言う構造体を定義しています。Celsius 構造体は、異なる温度スケールからの値を持つ構造体の新しいインスタンスを初期化する、init(fromFahrenheit:)init(fromKelvin:) と言う2つのカスタム・イニシャライザを実装しています。


  1. struct Celsius {
  2.        var temperatureInCelsius: Double
  3.        init(fromFahrenheit fahrenheit: Double) {
  4.                temperatureInCelsius = (fahrenheit - 32.0) / 1.8
  5.        }
  6.        init(fromKelvin kelvin: Double) {
  7.                temperatureInCelsius = kelvin - 273.15
  8.        }
  9. }
  10. let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
  11. // boilingPointOfWater.temperatureInCelsius is 100.0
  12. let freezingPointOfWater = Celsius(fromKelvin: 273.15)
  13. // freezingPointOfWater.temperatureInCelsius is 0.0


最初のイニシャライザには fromFahrenheit の引数ラベルと fahrenheit のパラメータ名を持つ一つの初期化パラメータがあります。二番目のイニシャライザには、fromKelvin の引数ラベルと kelvin のパラメータ名を持つ一つの初期化パラメータがあります。どちらもイニシャライザはそれらの一つの引数を、対応する摂氏の値に変換し、temperatureInCelsius というプロパティにその値を格納します。



パラメータ名と引数ラベル


関数やメソッドのパラメータと同様に、初期化パラメータは、イニシャライザの本体内で使用するためのパラメータ名と、イニシャライザを呼び出す時に使用するための引数ラベルの両方を持つことができます。


しかし、イニシャライザはそれらの括弧の前に、関数やメソッドが持つような、識別する関数名を持っていません。そのため、イニシャライザのパラメータの名前と型は、どのイニシャライザを呼び出すべきか識別する際に特に重要な役割を果たしています。このことから、Swift は、引数名をあなた自身が提供していない場合、イニシャライザ内の すべての パラメータに自動引数ラベルを提供します。


以下の例では、red、green、そして blue と言う3つの定数プロパティを有する Color と言う構造体を定義しています。これらのプロパティは、色の赤、緑、および青の量を示す、0.01.0 の間の値を格納します。


Color は、その赤、緑、青の成分の Double 型の3つの適切な名前のパラメータを持つイニシャライザを提供しています。Color はまた、3つの色成分すべてに同じ値を提供するために使用される、一つの white のパラメータで、第二のイニシャライザも提供します。


  1. struct Color {
  2.         let red, green, blue: Double
  3.         init(red: Double, green: Double, blue: Double) {
  4.                 self.red = red
  5.                 self.green = green
  6.                 self.blue = blue
  7.         }
  8.         init(white: Double) {
  9.                 red = white
  10.                 green = white
  11.                 blue = white
  12.         }
  13. }


どちらのイニシャライザも、各イニシャライザパラメータの名前付きの値を提供することで、新しい Color のインスタンスを作成するために使用できます:


  1. let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
  2. let halfGray = Color(white: 0.5)


引数のラベルを使用することなく、これらのイニシャライザを呼び出すことができないことに注意してください。引数ラベルは、それらが定義されている場合常にイニシャライザで使用されなければならず、それらを省略すると、コンパイル時エラーになります:


  1. let veryGreen = Color(0.0, 1.0, 0.0)
  2. // this reports a compile-time error - argument labels are required


引数ラベルのないイニシャライザのパラメータ


イニシャライザパラメータに引数ラベルを使用したくない場合は、デフォルトの動作をオーバーライドするために、そのパラメータの明示的な引数ラベルを書く代わりに、アンダースコア (_) を書いてください。


ここで、以前挙げた摂氏スケールで、既にある Double 値から新しい Celsius インスタンスを作成するための追加のイニシャライザを持つ、Celsius の例の拡張バージョンを挙げます:


  1. struct Celsius {
  2.         var temperatureInCelsius: Double
  3.         init(fromFahrenheit fahrenheit: Double) {
  4.                 temperatureInCelsius = (fahrenheit - 32.0) / 1.8
  5.         }
  6.         init(fromKelvin kelvin: Double) {
  7.                 temperatureInCelsius = kelvin - 273.15
  8.         }
  9.         init(_ celsius: Double) {
  10.                 temperatureInCelsius = celsius
  11.         }
  12. }
  13. let bodyTemperature = Celsius(37.0)
  14. // bodyTemperature.temperatureInCelsius is 37.0


イニシャライザの Celsius(37.0) の呼び出しは、引数ラベルを必要とせずに、その意図で明らかです。そのため、それは無名の Double 値を提供することで呼び出すことができるように、init(_ celsius: Double) としてこのイニシャライザを書くことは適切です。


Optional のプロパティ型


カスタム型が、"値のない" 事を論理的に許される格納されたプロパティを持っている場合ーその値は初期化時に設定することは多分できないので、または、いくつかの後の時点ーOptional 型のプロパティの宣言の時、"値のない" 事が許されているためです。Optional 型のプロパティは自動的に nil 値で初期化されるため、プロパティが故意に初期化中に"まだ値がない" ことを意図していることを示します。


次の例では、response と言う Optional の String プロパティを持つ、SurveyQuestion というクラスを定義しています。


  1. class SurveyQuestion {
  2.         var text: String
  3.         var response: String?
  4.         init(text: String) {
  5.         self.text = text
  6.         }
  7.         func ask() {
  8.                 print(text)
  9.         }
  10. }
  11. let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
  12. cheeseQuestion.ask()
  13. // prints "Do you like cheese?"
  14. cheeseQuestion.response = "Yes, I do like cheese."


調査の質問への答えは、それが問われるまでは知ることができず、そのため、response プロパティは、String? の型つまり "Optional の String" で宣言されています。それは、SurveyQuestion の新しいインスタンスが初期化される時、"まだ文字列がない" を意味する nil のデフォルト値が自動的に代入されています。



初期化中に定数プロパティへの代入


初期化が終了する時までに値を定義して設定することにより、初期化中の任意の時点で定数プロパティに値を代入できます。



注意: クラス・インスタンスの場合、定数プロパティはそれを導入するクラスによってのみ初期化中に変更できます。これは、サブクラスによって変更することはできません。


SurveyQuestion の上記の例を修正して質問の text プロパティに、変数プロパティではなく定数プロパティを使うようにして、SurveyQuestion インスタンスが一度作成されると question が変更されないことを示すためにそう修正します。text プロパティは、現在定数であっても、それはまだクラスのイニシャライザ内で設定することができます:


  1. class SurveyQuestion {
  2.         let text: String
  3.         var response: String?
  4.         init(text: String) {
  5.                 self.text = text
  6.         }
  7.         func ask() {
  8.                 print(text)
  9.         }
  10. }
  11. let beetsQuestion = SurveyQuestion(text: "How about beets?")
  12. beetsQuestion.ask()
  13. // prints "How about beets?"
  14. beetsQuestion.response = "I also like beets. (But not with cheese.)"


デフォルトのイニシャライザ


Swift は、そのすべてのプロパティにデフォルト値を提供し、少なくとも一つのイニシャライザ自体を提供していない全ての構造体またはクラスに デフォルトのイニシャライザ を提供します。デフォルトのイニシャライザは、それらのデフォルト値に設定した、そのプロパティのすべてで新しいインスタンスを単に作成します。


以下の例では、買い物リスト内のアイテム名前、量、及び購入状態をカプセル化した ShoppingListItem というクラスを定義しています。


  1. class ShoppingListItem {
  2.         var name: String?
  3.         var quantity = 1
  4.         var purchased = false
  5. }
  6. var item = ShoppingListItem()


ShoppingListItem クラスのすべてのプロパティにはデフォルト値があり、それはスーパークラスのない基底クラスであるため、ShoppingListItem は自動的に、それらのデフォルト値に設定されるそのプロパティのすべてに新しいインスタンスを作成する、デフォルトのイニシャライザの実装を獲得しています。(name プロパティは optional の String プロパティですので、この値はコードで書かれていませんが、nil のデフォルト値を自動的に受け取ります。) 上記の例では、ShoppingListItem() として書かれるイニシャライザの構文を持つクラスの新しいインスタンスを作成するために ShoppingListItem クラスのデフォルトイニシャライザを使用しており、そして item と言う変数に、この新しいインスタンスを代入します。



構造体型のためのメンバ化イニシャライザ


構造体型が独自のカスタムイニシャライザを全く定義しない場合、それらは、自動的に メンバ化イニシャライザ を受け取ります。デフォルトのイニシャライザとは異なり、構造体は、それがデフォルト値を持たない格納されたプロパティを持っている場合でも、メンバ化イニシャライザを受け取ります。


メンバ化イニシャライザは、新たな構造体インスタンスのメンバ・プロパティを初期化する近道の方法です。新しいインスタンスのプロパティ用の初期値は、名前でメンバ化イニシャライザに渡すことができます。


以下の例では、widthheight と言う二つのプロパティを持つ Size と言う構造体を定義しています。どちらのプロパティも 0.0 のデフォルト値を代入される Double 型であることが推測されます。


Size 構造体は、init(width:height:) のメンバ化イニシャライザを自動的に受け取り、それで新しい Size インスタンスを初期化できます:


  1. struct Size {
  2.         var width = 0.0, height = 0.0
  3. }
  4. let twoByTwo = Size(width: 2.0, height: 2.0)



値型のイニシャライザデリゲート


イニシャライザは、インスタンスの初期化の一部を実行するために他のイニシャライザを呼び出すことができます。イニシャライザデリゲート として知られるこのプロセスで、複数のイニシャライザ間でのコードの重複を避けることができます。


イニシャライザデリゲートがいかに働くかと、どのような形のデリゲートが許可されているかのルールについては、値型とクラス型で異なります。値型 (構造体と列挙型) は継承をサポートしておらず、それらだけが、自分自身を提供する別のイニシャライザにデリゲートすることができるので、それらのイニシャライザのデリゲートプロセスは、比較的簡単です。しかし、継承 で説明したようにクラスは、他のクラスから継承できます。これは、クラスが、それらが継承するすべての格納されたプロパティが、初期化中に適切な値を代入されることを確実にするための追加的な責任があることを意味します。これらの責任については、以下の クラスの継承と初期化 で説明します。


値型の場合、独自のカスタム・イニシャライザを書くときに同じ値型から他のイニシャライザを参照するために self.init を使用して下さい。イニシャライザ内からだけ self.init を呼び出すことができます。


値型のカスタム・イニシャライザを定義する場合、その型用のデフォルト・イニシャライザ (または構造体である場合、メンバ化イニシャライザ) に、もはやアクセスできなくなることに注意してください。この制約は、より複雑なイニシャライザで提供される追加の必須設定では、誰かが誤って代わりに自動イニシャライザのいずれか一つを使用したことによる事態を防止できます。



注意: 必要であれば、カスタムの値型は、デフォルトのイニシャライザとメンバ化イニシャライザで初期化可能であり、また、独自のカスタムのイニシャライザで、値型のオリジナルの実装の一部としてではなく、拡張機能で、カスタムのイニシャライザを書いて下さい。詳細については、拡張機能 を参照してください。


以下の例では、幾何学の長方形を表すためにカスタムの Rect 構造体を定義しています。例では、SizePoint と言う2つのサポートする構造体を必要とし、両方共それらのプロパティのすべてに 0.0 のデフォルト値を提供します。


  1. struct Size {
  2.         var width = 0.0, height = 0.0
  3. }
  4. struct Point {
  5.         var x = 0.0, y = 0.0
  6. }


以下の3つの方法のうちどれか一つで Rect 構造体を初期化できます:originsize プロパティ値をデフォルトのゼロで初期化する事によって、また特定の原点とサイズを提供することで、または、特定の中心点とサイズを提供する事によって。これらの初期化オプションは、 Rect 構造体の定義の一部である3つのカスタムイニシャライザで表わされます。


  1. struct Rect {
  2.         var origin = Point()
  3.         var size = Size()
  4.         init() {}
  5.         init(origin: Point, size: Size) {
  6.                 self.origin = origin
  7.                 self.size = size
  8.         }
  9.         init(center: Point, size: Size) {
  10.                 let originX = center.x - (size.width / 2)
  11.                 let originY = center.y - (size.height / 2)
  12.                 self.init(origin: Point(x: originX, y: originY), size: size)
  13.         }
  14. }


最初の Rect イニシャライザ、init() は、機能的には、独自のカスタムのイニシャライザを持っていない場合、構造体が受けただろう、デフォルトのイニシャライザと同じです。このイニシャライザには、中括弧 {} の空のペアで表される空の本体があります。このイニシャライザを呼び出すと、それらのプロパティの定義から、Point(x: 0.0, y: 0.0)Size(width: 0.0, height: 0.0) のデフォルト値で初期化された originsize プロパティの Rect インスタンスを返します。


  1. let basicRect = Rect()
  2. // basicRect's origin is (0.0, 0.0) and its size is (0.0, 0.0)


2つ目の Rect イニシャライザ、init(origin:size:)、は機能的には、独自のカスタムイニシャライザを持っていない場合、構造体が受けただろう、メンバ化イニシャライザと同じです。このイニシャライザは、適切な格納されたプロパティに、originsize 引数の値を単に代入します。


  1. let originRect = Rect(origin: Point(x: 2.0, y: 2.0),
  2.         size: Size(width: 5.0, height: 5.0))
  3. // originRect's origin is (2.0, 2.0) and its size is (5.0, 5.0)


3つ目の Rect イニシャライザ、init(center:size:) は、少し複雑です。これは、center の点と size の値に基づいて適切な原点を計算することによって始まります。それはその後 init(origin:size:) のイニシャライザを呼び出し(または デリゲート し)、適切なプロパティに新しい原点とサイズの値を格納します:


  1. let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
  2.         size: Size(width: 3.0, height: 3.0))
  3. // centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)


init(center:size:) イニシャライザは、それ自体適切なプロパティに originsize の新しい値を代入することができました。しかし、init(center:size:) イニシャライザにとっては、その機能を既に正確に提供している既存のイニシャライザを利用するほうが、便利(意図がより明確) です。



注意: init()init(origin:size:) イニシャライザを自分自身で定義せずに、この例を書く事く別の方法は、拡張機能 を参照してください。


クラスの継承と初期化


そのスーパークラスから継承したクラスの全てのプロパティを含むクラスの格納されたプロパティは全て、初期化時に初期値を代入され なければなりません。


Swift は、全ての格納されたプロパティが、初期値を確実に受け取るのを助ける、クラス型のイニシャライザを2種類定義しています。これらは、指定イニシャライザとコンビニエンスイニシャライザとして知られています。



指定イニシャライザとコンビニエンスイニシャライザ


指定イニシャライザ は、クラスの第一のイニシャライザです。指定イニシャライザはそのクラスによって導入されたすべてのプロパティを完全に初期化し、スーパークラスの連鎖の初期化プロセスを継続するために適切なスーパークラスのイニシャライザを呼び出します。


クラスは、非常に少数の指定イニシャライザしか持たない傾向があり、クラスが1つしかイニシャライザを持たないことが非常に一般的です。指定イニシャライザは、初期化が行われ、それを介して初期化プロセスがスーパークラスの連鎖を続ける事を通す "漏斗" 点です。


すべてのクラスは、少なくとも1つの指定イニシャライザを持っていなければなりません。いくつかの場合、この要件は、1つ以上の指定イニシャライザをスーパークラスから継承する事により満たされますが、この事は後に述べる 自動イニシャライザの継承 で説明します。


コンビニエンスイニシャライザ は、クラスのための二次的な、サポートするイニシャライザです。デフォルト値に設定する指定イニシャライザのパラメータの一部を持つコンビニエンスイニシャライザと同じクラスからの指定イニシャライザを呼び出すためにコンビニエンスイニシャライザを定義できます。また、特定の使用ケースや入力の値型のため、そのクラスのインスタンスを作成するためにコンビニエンスイニシャライザを定義できます。


クラスがコンビニエンスイニシャライザを必要としない場合には、それらを提供する必要はありません。一般的な初期化パターンへの近道が時間を節約するか、意図を明確にしてクラスの初期化を行う時にはいつでも、コンビニエンスイニシャライザを作成して下さい。



指定とコンビニエンスイニシャライザの構文


クラスの指定イニシャライザは値型の単純なイニシャライザと同じに書かれます:


init( ) {

       

}



コンビニエンスイニシャライザは、同じスタイルで書かれますが、スペースで区切って init キーワードの前に convenience 修飾子を書きます。


convenience init( ) {

       

}



クラス型のイニシャライザデリゲート


指定とコンビニエンスイニシャライザの間の関係を簡単にするため、Swift は、以下の3つのルールをイニシャライザ間のデリゲート呼び出しに適用します。


規則その1

指定イニシャライザは、そのすぐ上のスーパークラスから指定イニシャライザを呼び出さなければなりません。


規則その2

コンビニエンスイニシャライザは、同じ クラスから別のイニシャライザを呼び出さなければなりません。


規則その3

コンビニエンスイニシャライザは、最終的には指定イニシャライザを呼び出さなければなりません。


これを覚える簡単な方法は次のとおりです。


これらの規則を、以下の図に示します:



initializerDelegation01_2x


ここで、スーパークラスは、一つの指定イニシャライザと2つのコンビニエンスイニシャライザを持っています。一つのコンビニエンスイニシャライザは別のコンビニエンスイニシャライザを呼び出し、それは順番に、一つの指定イニシャライザを呼び出します。これは、上記の規則その2およびその3を満足します。スーパークラスは、それ自体はさらにスーパークラスを持っておらず、したがって規則その1は適用されません。


この図のサブクラスは、2つの指定イニシャライザと1つのコンビニエンスイニシャライザを持っています。コンビニエンスイニシャライザは、同じクラスからは別のイニシャライザしか呼び出せないので、2つの指定イニシャライザのうち一つを呼び出さなければなりません。これは、上記の規則その2およびその3を満足します。両方の指定イニシャライザとも、上記の規則その1を満たすために、スーパークラスから一つの指定イニシャライザを呼び出さなければなりません。


注意: これらの規則は、クラスのユーザーが、各クラスのインスタンスを 作成する 方法には影響しません。上図の全てのイニシャライザは、それらが属するクラスの、完全に初期化されたインスタンスを作成するために使用できます。規則は、あなたがクラスのイニシャライザの実装をどう書くかのみに影響します。


下の図は、4つのクラスの、より複雑なクラス階層を示しています。これは、連鎖内のクラス間の相互関係を簡素化する、クラスの初期化の "漏斗" の点として、この階層内でどのように指定イニシャライザが振る舞うかを示しています。


initializerDelegation02_2x



二相の初期化


Swift におけるクラスの初期化は2段階のプロセスを経ます。第一相では、格納された各プロパティは、それを導入したクラスによって初期値が代入されます。すべての格納されたプロパティの初期状態が一度決定されると、第二相が開始し、各クラスは、新しいインスタンスが使用可能な状態とみなされるずっと前に、その格納されたプロパティをカスタム化する機会が与えられます。


二相の初期化プロセスの使用は、初期化を安全にし、クラス階層内の各クラスに完全な柔軟性をまだ与えます。二相の初期化は、それらが初期化される前に、アクセスされる事をプロパティ値から防ぎ、かつ予想外に、別のイニシャライザによって異なる値に設定される事からプロパティ値を防ぎます。



注意: Swift の二相の初期化プロセスは、Objective-C での初期化と似ています。主な違いは、第一段階の間に、Objective-C では、ゼロまたは NULL 値 (0nil のような) をすべてのプロパティに代入することです。Swift の初期化の流れは、カスタムの初期値を設定し、0nil が有効なデフォルト値ではない型に対応できることで、より柔軟性があります。


二相の初期化がエラーなしで完了したことを Swift のコンパイラは確認するために、役立つ安全チェックを4つ実行します。


安全確認その1

指定イニシャライザは、そのクラスによって導入されたプロパティをすべて、スーパークラスのイニシャライザにまでデリゲートする前に初期化されることを確認しなければなりません。


上記で述べたように、オブジェクトのメモリは、その格納されたプロパティのすべての初期状態が知られた時にのみ、完全に初期化されたとみなされます。この規則を満足するために、指定イニシャライザは、連鎖を登って行く前に、すべての独自のプロパティが初期化されていることを確認しなければなりません。


安全確認その2

指定イニシャライザは、継承されたプロパティに値を代入する前に、スーパークラスのイニシャライザまでデリゲートしなければなりません。そうでないと、指定イニシャライザが代入した新しい値は、独自の初期化の一部として、スーパークラスによって上書きされます。


安全確認その3

コンビニエンスイニシャライザは、全ての プロパティに値を代入する前に、別のイニシャライザにデリゲートしなければなりません (同じクラスで定義されたプロパティを含む)。そうでないと、コンビニエンスイニシャライザが代入した新しい値は、独自のクラスの指定イニシャライザで上書きされます。


安全確認その4

イニシャライザは、全てのインスタンスメソッドを呼び出す事ができるとは限らず、全てのインスタンス·プロパティの値を読む事、または初期化の第一相が完了するまでは値として self を参照する事もできません。


クラスのインスタンスは、第一相が終了するまでは、完全には有効でありません。プロパティは、アクセスすることだけができ、クラスインスタンスが第一相の終了時に有効であることが分かれば、メソッドは、呼び出すことだけができます。


ここで、二相の初期化が上記の4つの安全確認に基づいて、果たしている役割は以下のとおりです。


第一相

第二相

ここで、第一相が、仮想的なサブクラスとスーパークラスの初期化呼び出しでどのように見えるかを示します:



twoPhaseInitialization01_2x


この例では、初期化は、サブクラスのコンビニエンスイニシャライザの呼び出しで始まります。このコンビニエンスイニシャライザは、まだどのプロパティも変更できません。同じクラスからの指定イニシャライザをデリゲートするためそれは横切って行きます。


指定イニシャライザは、安全確認その1に従って、サブクラスのすべてのプロパティが、値を持っていることを確認します。そして、連鎖を登って初期化を継続して、そのスーパークラスの指定イニシャライザを呼び出します。


スーパークラスの指定イニシャライザは、スーパークラスのすべてのプロパティが値を持っていることを確認します。そこに初期化すべき更なるスーパークラスはないので、したがって、それ以上のデリゲートは必要ありません。


スーパークラスのすべてのプロパティが初期値を持つやいなや、そのメモリは完全に初期化しているとみなされ、第一相が完了します。


ここで第二相が同じ初期化呼び出しでどのように見えるか示します:



twoPhaseInitialization02_2x


スーパークラスの指定イニシャライザには (それは必要ではありませんが) さらにインスタンスをカスタム化する機会があります。


スーパークラスの指定イニシャライザが終了すると、サブクラスの指定イニシャライザは、(再び、それは必要ではありませんが) 追加のカスタム化を行うことができます。


最後に、サブクラスの指定イニシャライザが終了すると、元々呼ばれていたコンビニエンスイニシャライザは追加のカスタム化を行うことができます。



イニシャライザ継承とオーバーライド


Objective-C のサブクラスとは異なり、Swift のサブクラスは、デフォルトでは、そのスーパークラスのイニシャライザを継承しません。Swift のアプローチは、スーパークラスからの簡単なイニシャライザが、より専門的なサブクラスによって継承され、完全にまたは正しく初期化されないサブクラスの新しいインスタンスを作成するために使用されている状況を防ぐことができます。


注意: スーパークラスのイニシャライザは、ある特定の状況では継承 されます が、それは、安全かつ適切な場合にのみ、そのようにされます。詳細については、下記の 自動イニシャライザの継承 を参照してください。

カスタムサブクラスがそのスーパークラスと1つ以上の同じイニシャライザを提示したい場合には、サブクラス内のそれらのイニシャライザのカスタムの実装を提供できます。


スーパークラスの 指定 イニシャライザに一致するサブクラスイニシャライザを書くときには、その指定イニシャライザのオーバーライドを効果的に提供できます。そのため、サブクラスのイニシャライザの定義の前に override 修飾子を書かなければなりません。これは、デフォルトのイニシャライザ で説明したように、自動的に提供されているデフォルトのイニシャライザをオーバーライドしている場合にも当てはまります。


オーバーライドされたプロパティ、メソッド、またはサブスクリプトの場合と同様に、override 修飾子の存在は、スーパークラスがオーバーライドされるべき一致する指定イニシャライザがあることを確認するように Swift を促して、意図したとおりに、オーバーライドするイニシャライザのためのパラメータが指定されていることを検証します。


注意: イニシャライザのサブクラスの実装がコンビニエンスイニシャライザであっても、スーパークラスの指定イニシャライザをオーバーライドするときは、必ず override 修飾子を書いて下さい。

逆に、スーパークラスの コンビニエンス イニシャライザに一致するサブクラスイニシャライザを書く場合、そのスーパークラスコンビニエンスイニシャライザは クラス型のイニシャライザデリゲート で上述した規則に従って、サブクラスによって直接呼び出されることは決してありません。そのため、サブクラスはスーパークラスイニシャライザのオーバーライドを提供していません (厳密に言えば)。その結果、スーパークラスのコンビニエンスイニシャライザに一致する実装を提供するときには override 修飾子を書かないで下さい。


以下の例では、Vehicle と言う基本クラスを定義しています。この基本クラスは numberOfWheels と言う 0Int デフォルト値を持つ、格納されたプロパティを宣言しています。numberOfWheels プロパティは、車両の特性の String の説明を作成するために description と言う計算されたプロパティで使用されます。


  1. class Vehicle {
  2.        var numberOfWheels = 0
  3.        var description: String {
  4.                return "\(numberOfWheels) wheel(s)"
  5.        }
  6. }


Vehicle クラスは、唯一の格納されたプロパティのデフォルト値を提供し、それ自身は全くカスタムイニシャライザを提供していません。その結果、デフォルトのイニシャライザ で説明したように、デフォルトのイニシャライザを自動的に受け取ります。デフォルトのイニシャライザ (使用可能な時) は、常にクラスの指定イニシャライザで、0numberOfWheels で新しい Vehicle のインスタンスを作成するために使用できます:


  1. let vehicle = Vehicle()
  2. print("Vehicle: \(vehicle.description)")
  3. // Vehicle: 0 wheel(s)


次の例では、Bicycle と言う Vehicle のサブクラスを定義しています:


  1. class Bicycle: Vehicle {
  2.         override init() {
  3.                 super.init()
  4.                 numberOfWheels = 2
  5.         }
  6. }


Bicycle サブクラスはカスタム指定イニシャライザ、init() を定義しています。この指定イニシャライザは、Bicycle のスーパークラスからの指定イニシャライザと一致するので、このイニシャライザの Bicycle バージョンは override 修飾子でマークされています。


Bicycleinit() イニシャライザは super.init() を呼び出すことで始まり、Bicycle クラスのスーパークラスである、 Vehicle のデフォルトのイニシャライザを呼び出します。これは Bicycle がプロパティを変更する機会を得る前に numberOfWheels の継承したプロパティが、Vehicle によって初期化されることを保証します。 super.init() を呼び出した後、numberOfWheels の元の値は新しい値である 2 に置き換えられます。


  1. let bicycle = Bicycle()
  2. print("Bicycle: \(bicycle.description)")
  3. // Bicycle: 2 wheel(s)


注意: サブクラスは、初期化中に、継承した変数のプロパティを変更することができますが、継承した定数のプロパティを変更することはできません。


自動イニシャライザの継承


前述したように、サブクラスはデフォルトでは、そのスーパークラスのイニシャライザを継承しません。しかし、特定の条件が満たされた場合は、スーパークラスのイニシャライザが自動的に継承 されます。実際には、これは多くの一般的なシナリオでイニシャライザオーバーライドを書く必要がない事を意味し、そうすることが安全であるときはいつでも、最小限の努力でスーパークラスのイニシャライザを継承できることを意味します。


サブクラスで導入したいずれかの新しいプロパティのデフォルト値を提供すると仮定すると、以下の2つの規則が適用されます。


規則その1

サブクラスが、全く指定イニシャライザを定義しない場合には、そのスーパークラスの指定イニシャライザのすべてを自動的に継承します。


規則その2

サブクラスは、そのスーパークラスの指定イニシャライザの 全て の実装を提供しますが、規則その1のようにそれらを継承することによって、またはその定義の一部として、カスタムの実装を提供することのどちらかで行い、それはスーパークラスのコンビニエンスイニシャライザのすべてを自動的に継承します。


これらの規則は、サブクラスがさらにコンビニエンスイニシャライザを追加した場合でも適用されます。



注意: サブクラスは、規則その2を満たす一環として、サブクラスのコンビニエンスイニシャライザとして、スーパークラスの指定イニシャライザを実装できます。



実際の指定とコンビニエンスイニシャライザ


以下の例は、実際の指定イニシャライザ、コンビニエンスイニシャライザ、及び自動イニシャライザの継承を示しています。この例は、Food、RecipeIngredient、 および ShoppingListItem と言う3つのクラスの階層を定義し、それらのイニシャライザがどのように相互作用するかを示しています。


階層内の基本クラスは、食品の名前をカプセル化する単純なクラスである、Foodと言う名前です。Food クラスは、name と言う一つの String プロパティを導入し、Food インスタンスを作成するための2つのイニシャライザを提供します。


  1. class Food {
  2.         var name: String
  3.         init(name: String) {
  4.                 self.name = name
  5.         }
  6.         convenience init() {
  7.                 self.init(name: "[Unnamed]")
  8.         }
  9. }


以下の図は、Food クラスのイニシャライザ連鎖を示しています。



initializersExample01_2x


クラスは、デフォルトのメンバ化イニシャライザを持っていないので、Food クラスは、name という一つの引数を取る指定イニシャライザを提供しています。このイニシャライザは、特定の名前を持つ新しい Food インスタンスを作成するために使用できます:


  1. let namedMeat = Food(name: "Bacon")
  2. // namedMeat's name is "Bacon"


Food クラスからの init(name: String) イニシャライザは、新しい Food インスタンスのすべての格納されたプロパティが、完全に初期化されたことを保証するため、指定 イニシャライザとして提供されています。Food クラスは、スーパークラスを持っておらず、init(name: String) イニシャライザはその初期化を完了するために super.init() を呼び出す必要はありません。


Food クラスはまた、引数なしの コンビニエンス イニシャライザ、init() も、提供しています。init() イニシャライザが Food クラスの init(name: String) に渡ってデリゲートすることで新たな food のデフォルトのプレースホルダ名を [Unnamed]name 値で提供します:


  1. let mysteryMeat = Food()
  2. // mysteryMeat's name is "[Unnamed]"


階層内の第二のクラスは RecipeIngredient と言う Food のサブクラスです。RecipeIngredient クラスは、料理レシピの原料をモデルにしています。これは、RecipeIngredient インスタンスを作成するために2つのイニシャライザを定義して (Food から継承する name プロパティに加えて) Quantity と言う Int プロパティを導入しています。


  1. class RecipeIngredient: Food {
  2.         var quantity: Int
  3.         init(name: String, quantity: Int) {
  4.                 self.quantity = quantity
  5.                 super.init(name: name)
  6.         }
  7.         override convenience init(name: String) {
  8.                 self.init(name: name, quantity: 1)
  9.         }
  10. }


以下の図は、RecipeIngredient クラスのイニシャライザの連鎖を示しています。


initializersExample02_2x


RecipeIngredient クラスは、一つの指定イニシャライザを持っており、それは新しい RecipeIngredient インスタンスのすべてのプロパティを設定するために使用できる、init(name: String,quantity: Int) です。このイニシャライザは 渡された quantity 引数を、RecipeIngredient によって導入された唯一の新しいプロパティである、 quantity プロパティに代入することによって開始します。そうするとイニシャライザは、 Foodクラスの init(name: String) までのイニシャライザをデリゲートします。このプロセスは、上記の 二相の初期化 からの安全確認その1を満たします。


RecipeIngredient もコンビニエンスイニシャライザ、init(name: String) を定義し、名前だけで RecipeIngredient インスタンスを作成するために使用されます。このコンビニエンスイニシャライザは、明示的な量 (quantity) なしで作られている全ての RecipeIngredient インスタンスに 1 の量を想定しています。このコンビニエンスイニシャライザの定義は RecipeIngredient インスタンスをより速く、より便利に作成できるようにし、そしていくつかのちょっとした量の RecipeIngredient インスタンスを作成するときにコードの重複を避けることができます。このコンビニエンスイニシャライザは 1quantity の値を渡して、クラスの指定イニシャライザを横切って渡り単にデリゲートします。


Init(name: String) コンビニエンスイニシャライザは、Food からの 指定 イニシャライザの init(name: String) と同じパラメータを取る RecipeIngredient が提供します。このコンビニエンスイニシャライザは、そのスーパークラスからの指定イニシャライザをオーバーライドしますので (イニシャライザ継承とオーバーライド で説明したように)、それは override 修飾子でマークされなければなりません。


RecipeIngredient は、init(name: String) イニシャライザをコンビニエンスイニシャライザとして提供していますが、RecipeIngredient は、それにもかかわらず、そのスーパークラスの指定イニシャライザのすべての実装を提供しています。したがって、RecipeIngredient もそのスーパークラスのコンビニエンスイニシャライザのすべてを自動的に継承します。


この例では、RecipeIngredient のスーパークラスは、Food で、それは init() と言う一つのコンビニエンスイニシャライザを持っています。このイニシャライザは、したがって RecipeIngredient によって継承されます。 init() 関数の継承バージョンは Food バージョン と完全に同じく機能しますが、Food バージョンと言うよりは init(name: String)RecipeIngredient バージョンへデリゲートする事を除きます。


これらの3つのイニシャライザは全部、新しい RecipeIngredient インスタンスを作成するために使用できます:


  1. let oneMysteryItem = RecipeIngredient()
  2. let oneBacon = RecipeIngredient(name: "Bacon")
  3. let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)


階層内の3番目で最後のクラスは ShoppingListItem と言う RecipeIngredient のサブクラスです。ShoppingListItem クラスは、買い物リストに表われるレシピの原料をモデルにしています。


買い物リスト内のすべての項目は、"未購入" として始まります。この事実を表現して、ShoppingListItem は、false のデフォルト値を持つ purchased と言うブール型プロパティを導入します。ShoppingListItem はまた計算された description プロパティを追加し、これは ShoppingListItem インスタンスのテキスト記述を提供します:


  1. class ShoppingListItem: RecipeIngredient {
  2.         var purchased = false
  3.         var description: String {
  4.                 var output = "\(quantity) x \(name)"
  5.                 output += purchased ? " ✔" : " ✘"
  6.                 return output
  7.         }
  8. }


注意: ShoppinListItem は、買い物の項目は (ここでのモデルとしては) 常に未購入から始めるので、purchased の初期値を提供するイニシャライザは定義していません。


それが導入した全てのプロパティのデフォルト値を提供し、どんなイニシャライザもそれ自身定義していないので、ShoppingListItem はそのスーパークラスからの指定とコンビニエンスイニシャライザの すべて を自動的に継承します。


以下の図は、3つのクラスすべての全体的なイニシャライザ連鎖を示しています。


initializersExample03_2x


新しい ShoppingListItem インスタンスを作成するために、継承されたイニシャライザの3つすべてを使用できます。


  1. var breakfastList = [
  2.         ShoppingListItem(),
  3.         ShoppingListItem(name: "Bacon"),
  4.         ShoppingListItem(name: "Eggs", quantity: 6),
  5. ]
  6. breakfastList[0].name = "Orange juice"
  7. breakfastList[0].purchased = true
  8. for item in breakfastList {
  9.         print(item.description)
  10. }
  11. // 1 x Orange juice ✔
  12. // 1 x Bacon ✘
  13. // 6 x Eggs ✘


ここで、breakfastList と言う新しい配列が3つの新しい ShoppingListItem インスタンスを含む配列リテラルから作成されます。配列の型は、[ShoppingListItem] であることが推測されます。配列が作成された後、配列の先頭の ShoppingListItem の名前は "[Unnamed]" から "Orange juice" に変更され、それが購入されたものとしてマークされます。配列内の各項目の説明を印刷すると、予想されるようにデフォルト状態が設定されていることを示します。



失敗可能イニシャライザ


初期化が失敗する可能性があるクラス、構造体、または列挙型を定義すると便利な場合があります。この障害は、無効な初期化パラメータ値によって引き起こされる場合があり、必要な外部リソースがない場合、または、初期化が成功する事を防止するいくつかの他の条件によって起こります。


初期条件が失敗する場合に対処するために、クラス、構造体、または列挙型の定義の一部として、1つ以上の失敗可能(failable)イニシャライザを定義できます。init キーワードの後に疑問符を配置して失敗可能イニシャライザを書いて下さい(init?)。



注意: failable と同じパラメータ型と名前の nonfailable イニシャライザを定義することはできません。


失敗可能(failable)イニシャライザは、初期化する型の optional の値を作成します。初期化の失敗が引き起こされる点を示すために、失敗可能イニシャライザ内に return nil を書いて下さい。



注意: 厳密に言えば、イニシャライザは値を返しません。むしろ、その役割は、初期化が終わった時点で self が完全に正しく初期化された事を保証することです。初期化の失敗を引き起こすために return nil を書きますが、初期化の成功を示すために、return キーワードを使用しないでください。


たとえば、数値型の変換のために 失費可能 (failable) イニシャライザが実装されています。数値型間の変換を確実に行うには、init(exactly:) イニシャライザを使用して下さい。型変換が値を保持できない場合、イニシャライザは失敗します。


  1. let wholeNumber: Double = 12345.0
  2. let pi = 3.14159
  3. if let valueMaintained = Int(exactly: wholeNumber) {
  4.         print("\(wholeNumber) conversion to Int maintains value of \(valueMaintained)")
  5. }
  6. // Prints "12345.0 conversion to Int maintains value of 12345"
  7. let valueChanged = Int(exactly: pi)
  8. // valueChanged is of type Int?, not Int
  9. if valueChanged == nil {
  10.         print("\(pi) conversion to Int does not maintain value")
  11. }
  12. // Prints "3.14159 conversion to Int does not maintain value"


以下の例では、species と言う定数の String プロパティと、Animal と言う構造体を定義しています。Animal の構造体はまた、species と言う一つのパラメータで失敗可能イニシャライザも定義しています。このイニシャライザは、イニシャライザに渡された species の値が空の文字列であるかどうかチェックします。空の文字列が見つかった場合、初期化エラーが引き起こされます。そうでなければ、species プロパティ値が設定され、初期化は成功します。


  1. struct Animal {
  2.         let species: String
  3.         init?(species: String) {
  4.                 if species.isEmpty { return nil }
  5.                 self.species = species
  6.         }
  7. }


新しい Animal インスタンスを初期化し、初期化が成功したかどうかを確認しようとするにはこの失敗可能イニシャライザを使用できます。


  1. let someCreature = Animal(species: "Giraffe")
  2. // someCreature is of type Animal?, not Animal
  3. if let giraffe = someCreature {
  4.         print("An animal was initialized with a species of \(giraffe.species)")
  5. }
  6. // prints "An animal was initialized with a species of Giraffe"


失敗可能イニシャライザの species パラメータに空の文字列値を渡すと、イニシャライザは、初期化失敗を引き起こします:


  1. let anonymousCreature = Animal(species: "")
  2. // anonymousCreature is of type Animal?, not Animal
  3. if anonymousCreature == nil {
  4.         print("The anonymous creature could not be initialized")
  5. }
  6. // prints "The anonymous creature could not be initialized"


注意: 空の文字列値 (例えば、"Giraffe" ではなく"") のチェックは、optionalString 値が存在しないことを示すために nil をチェックするのと同じではありません。上記の例では、空の文字列 ("") は、有効な、optional でない String です。しかし、animal がその species プロパティの値として空の文字列を持つのは適切ではありません。この制限をモデル化するために、空の文字列が見つかった場合は、失敗可能イニシャライザは、初期化の失敗を引き起こします。



列挙型のための失敗可能イニシャライザ


1つ以上のパラメータに基づいて、適切な列挙型の case を選択する失敗可能イニシャライザを使用できます。提供されたパラメータが適切な列挙型の case に一致しない場合は、イニシャライザは失敗する可能性があります。


以下の例では、3つの可能な状態 (kelvin 絶対温度、celsius 摂氏、そして fahrenheit 華氏) で、TemperatureUnit と言う列挙型を定義しています。失敗可能イニシャライザは、温度記号を表す Character 値の適切な列挙型の case を見つけるために使用されています。


  1. enum TemperatureUnit {
  2.         case kelvin, celsius, fahrenheit
  3.         init?(symbol: Character) {
  4.                 switch symbol {
  5.                 case "K":
  6.                         self = .kelvin
  7.                 case "C":
  8.                         self = .celsius
  9.                 case "F":
  10.                         self = .fahrenheit
  11.                 default:
  12.                         return nil
  13.                 }
  14.         }
  15. }


3つの可能な状態の適切な列挙型の case を選択して、パラメータがこれらのいずれの状態とも一致しない場合、初期化が失敗を引き起こすと、この失敗可能イニシャライザを使用できます。


  1. let fahrenheitUnit = TemperatureUnit(symbol: "F")
  2. if fahrenheitUnit != nil {
  3.         print("This is a defined temperature unit, so initialization succeeded.")
  4. }
  5. // prints "This is a defined temperature unit, so initialization succeeded."
  6. let unknownUnit = TemperatureUnit(symbol: "X")
  7. if unknownUnit == nil {
  8.         print("This is not a defined temperature unit, so initialization failed.")
  9. }
  10. // prints "This is not a defined temperature unit, so initialization failed."


生の値を持つ列挙型のための失敗可能イニシャライザ


生の値を持つ列挙型は、自動的に init?(rawValue:) の失敗可能イニシャライザを受け取り、それは適切な生の値型の rawValue というパラメータを取り、一つが見つかった場合、一致する列挙型の case を選択し、または一致する値がない場合、初期化の失敗を引き起こします。


Character 型の生の値を使用するようにして、init?(rawValue:) イニシャライザを利用するには、上記の TemperatureUnit の例を書き換えて下さい:


  1. enum TemperatureUnit: Character {
  2.         case kelvin = "K", celsius = "C", fahrenheit = "F"
  3. }
  4. let fahrenheitUnit = TemperatureUnit(rawValue: "F")
  5. if fahrenheitUnit != nil {
  6.         print("This is a defined temperature unit, so initialization succeeded.")
  7. }
  8. // prints "This is a defined temperature unit, so initialization succeeded."
  9. let unknownUnit = TemperatureUnit(rawValue: "X")
  10. if unknownUnit == nil {
  11.         print("This is not a defined temperature unit, so initialization failed.")
  12. }
  13. // prints "This is not a defined temperature unit, so initialization failed."



初期化失敗の伝播


クラス、構造体、または列挙型の失敗可能イニシャライザは、同じクラス、構造体、または列挙型から別の失敗可能イニシャライザへ横切ってデリゲートできます。同様に、サブクラスの失敗可能イニシャライザは、スーパークラスの失敗可能イニシャライザまで登ってデリゲートできます。


どちらの場合でも、初期化に失敗する原因となる別のイニシャライザにデリゲートする場合、全体の初期化処理はすぐに失敗し、それ以上の初期化コードは実行されません。


注意: failable (失敗可能) イニシャライザも、nonfailable イニシャライザにデリゲートできます。そうでなければ失敗しない既存の初期化プロセスへの潜在的な障害状態を追加する必要がある場合は、この方法を使用して下さい。


以下の例は、CartItem と言う Product のサブクラスを定義しています。CartItem クラスは、オンラインのショッピングカート内のアイテムをモデルにしています。CartItem は、quantity と言う格納された定数のプロパティを導入し、このプロパティは少なくとも 1 の値を常に持っていることを保証します。


  1. class Product {
  2.         let name: String
  3.         init?(name: String) {
  4.                 if name.isEmpty { return nil }
  5.                 self.name = name
  6.         }
  7. }
  8. class CartItem: Product {
  9.         let quantity: Int
  10.         init?(name: String, quantity: Int) {
  11.                 if quantity < 1 { return nil }
  12.                 self.quantity = quantity
  13.                 super.init(name: name)
  14.         }
  15. }


CartItem 用の failable(失敗可能) イニシャライザは、それが 1 以上の quantity の値を受信したことを検証することにより開始します。quantity が無効の場合、全体の初期化プロセスはすぐに失敗し、さらなる初期化コードは実行されません。同様に、Product 用の failable(失敗可能) イニシャライザは、name の値をチェックし、name が空の文字列の場合、初期化プロセスはすぐに失敗します。


あなたが空でない name と 1 以上の quantity で CartItem インスタンスを作成した場合、初期化は成功します。


  1. if let twoSocks = CartItem(name: "sock", quantity: 2) {
  2.         print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")
  3. }
  4. // prints "Item: sock, quantity: 2"


quantity0CartItem インスタンスを作成しようとすると、CartItem イニシャライザは初期化に失敗します。


  1. if let zeroShirts = CartItem(name: "shirt", quantity: 0) {
  2.         print("Item: \(zeroShirts.name), quantity: \(zeroShirts.quantity)")
  3. } else {
  4.         print("Unable to initialize zero shirts")
  5. }
  6. // prints "Unable to initialize zero shirts"


同様に、空の name 値で CartItem インスタンスを作成しようとした場合も、スーパークラスの Product イニシャライザは初期化に失敗します。


  1. if let oneUnnamed = CartItem(name: "", quantity: 1) {
  2.         print("Item: \(oneUnnamed.name), quantity: \(oneUnnamed.quantity)")
  3. } else {
  4.         print("Unable to initialize one unnamed product")
  5. }
  6. // prints "Unable to initialize one unnamed product"



失敗可能イニシャライザのオーバーライド


他のすべてのイニシャライザのように、サブクラスでスーパークラスの失敗可能イニシャライザをオーバーライドすることができます。あるいは、サブクラスの 失敗できない(nonfailable) イニシャライザでスーパークラスの失敗可能イニシャライザをオーバーライドすることもできます。これで、スーパークラスの初期化ザが失敗することを許可されていても、初期化が失敗できないようにサブクラスを定義できるようになります。


失敗できないサブクラスのイニシャライザで失敗可能なスーパークラスのイニシャライザをオーバーライドする場合、スーパークラスのイニシャライザまで登って行きデリゲートする唯一の方法は、失敗可能スーパークラスイニシャライザの結果を強制的に開封することです。



注意: 失敗できないイニシャライザで失敗可能イニシャライザをオーバーライドできますが、その逆はできません。


以下の例では、Document と言うクラスを定義しています。このクラスは、空でない文字列値か nil のいずれかの name プロパティで初期化することができ、空の文字列にはならない document をモデルにしています。


  1. class Document {
  2.         var name: String?
  3.         // this initializer creates a document with a nil name value
  4.         init() {}
  5.         // this initializer creates a document with a non-empty name value
  6.         init?(name: String) {
  7.                 if name.isEmpty { return nil }
  8.                 self.name = name
  9.         }
  10. }


次の例では、AutomaticallyNamedDocument と言う Document のサブクラスを定義しています。 AutomaticallyNamedDocument サブクラスは、Document によって導入された指定イニシャライザを両方ともオーバーライドします。これらのオーバーライドは AutomaticallyNamedDocument インスタンスが "[Untitled]" の初期の name 値を持っていることを、インスタンスが名前なしで初期化されるか、または空の文字列が init(name:) イニシャライザに渡されるかどうか確認します:


  1. class AutomaticallyNamedDocument: Document {
  2.         override init() {
  3.                 super.init()
  4.                 self.name = "[Untitled]"
  5.         }
  6.         override init(name: String) {
  7.                 super.init()
  8.                 if name.isEmpty {
  9.                         self.name = "[Untitled]"
  10.                 } else {
  11.                         self.name = name
  12.                 }
  13.         }
  14. }


AutomaticallyNamedDocument は nonfailable の (失敗できない) init(name:) イニシャライザでスーパークラスの失敗可能 init?(name:) イニシャライザをオーバーライドしています。AutomaticallyNamedDocument はそのスーパークラスとは異なる方法で、空の文字列の場合に対応するので、そのイニシャライザは失敗する必要がなく、代わりにイニシャライザの nonfailable (失敗できない) バージョンを提供しています。


サブクラスの nonfailable (失敗できない)イニシャライザの実装の一部として、スーパークラスから失敗可能イニシャライザを呼び出すためにイニシャライザで強制的開封を使用できます。たとえば、以下の UntitledDocument サブクラスは、常に"[Untitled]" という名前が付けられ、それが初期化中に、そのスーパークラスから失敗可能な init(name:) イニシャライザを使用します。


  1. class UntitledDocument: Document {
  2.         override init() {
  3.                 super.init(name: "[Untitled]")!
  4.         }
  5. }

この場合、スーパークラスの init(name:) イニシャライザは、これまで名前として空の文字列と共に呼び出された場合、強制的な開封操作は実行時エラーになりました。しかし、文字列定数と共に呼び出されていますので、イニシャライザが失敗しないことを確認でき、実行時エラーは、この場合には発生しません。


init! の失敗可能イニシャライザ


通常は、init のキーワードの後に疑問符を書くことで、適切な型の optional インスタンスを作成し、失敗可能イニシャライザの定義 (init?)をします。あるいは、適切な型の暗黙的に開封された optional インスタンスを作成して失敗可能イニシャライザを定義できます。init のキーワードの後に、疑問符の代わりに感嘆符を書くことによってこれを行います (init!)。


init? から init! にデリゲートすることができ、またその逆もでき、そして init!init? をオーバーライドすることができ、その逆もできます。また、init から init! にデリゲートすることもできますが、そうすると init! イニシャライザが、初期化に失敗するとアサーションを引き起こします。



必須イニシャライザ


クラスのすべてのサブクラスは、そのイニシャライザを実装しなければならないことを示すために、クラスイニシャライザの定義の前に required (必須) の修飾語を書いて下さい:


  1. class SomeClass {
  2.         required init() {
  3.                 // initializer implementation goes here
  4.         }
  5. }


また、イニシャライザの必要性が連鎖の中ででさらなるサブクラスに適用されることを示すために、必須イニシャライザの全てのサブクラス実装の前に required 修飾子を書かなければなりません。必須指定イニシャライザをオーバーライドするときには、override 修飾子を書いてはいけません。


  1. class SomeSubclass: SomeClass {
  2.         required init() {
  3.                 // subclass implementation of the required initializer goes here
  4.         }
  5. }


注意: 継承されたイニシャライザで必要性を満たすことができる場合には、必須イニシャライザの明示的な実装を提供する必要はありません。



クロージャや関数でのデフォルトのプロパティ値設定


格納されたプロパティのデフォルト値が、いくつかのカスタム化や設定が必要な場合は、そのプロパティのカスタム化されたデフォルト値を提供するために、クロージャまたはグローバル関数を使用できます。プロパティが属する型の新しいインスタンスを初期化する時はいつでも、クロージャまたは関数が呼び出され、その戻り値は、プロパティのデフォルト値として代入されます。


これらの種類のクロージャや関数は、一般的にプロパティと同じ型の一時的な値を作成し、望みの初期状態を表わすためにその値を仕立て、その後プロパティのデフォルト値として使用されるべくその一時的な値を戻します。


ここで、クロージャがデフォルトのプロパティ値を提供するために使用される方法の骨格のアウトラインを挙げます。


  1. class SomeClass {
  2.         let someProperty: SomeType = {
  3.                 // create a default value for someProperty inside this closure
  4.                 // someValue must be of the same type as SomeType
  5.                 return someValue
  6.                 }()
  7. }


クロージャの終わりの中括弧に、括弧の空のペアが続いていることに注意してください。これは Swift にすぐにクロージャを実行するように指示します。これらの括弧を省略した場合、クロージャの戻り値ではなく、プロパティにクロージャ自体を代入しようとあなたはしています。


注意: プロパティを初期化するためにクロージャを使用する場合は、インスタンスの残りの部分はクロージャが実行された時点ではまだ初期化されていないことを覚えておいてください。これは、これらのプロパティがデフォルト値をたとえ持っていても、クロージャ内から他のどのプロパティ値にもアクセスできないことを意味します。また、暗黙の self プロパティを使用したり、またはインスタンスメソッドのどれも呼び出すことはできません。


以下の例は、チェスのゲームのためのボードをモデルにした、Chaessboard と言う構造体を定義します。チェスは、黒と白の正方形を交互にした、8×8 のボード上でプレイされます。


chessBoard_2x


このゲームボードを表すには、Chassboard の構造体は、64 の Bool 値の配列である boardColors と言う一つのプロパティを持っています。配列内の値が true は、黒い正方形を表し、値が false は、白い四角を表します。配列内の最初の項目は、ボードの一番左上の正方形を表し、配列内の最後の項目のは、ボード上の右下の正方形を表します。


boardColors 配列は、その色の値を設定するためのクロージャで初期化されます:


  1. struct Checssboard {
  2.         let boardColors: [Bool] = {
  3.                 var temporaryBoard = [Bool]()
  4.                 var isBlack = false
  5.                 for i in 1...8 {
  6.                         for j in 1...8 {
  7.                         temporaryBoard.append(isBlack)
  8.                         isBlack = !isBlack
  9.                         }
  10.                         isBlack = !isBlack
  11.                 }
  12.                 return temporaryBoard
  13.                 }()
  14.         func squareIsBlackAt(row: Int, column: Int) -> Bool {
  15.                 return boardColors[(row * 8) + column]
  16.         }
  17. }


新しい Chessboard インスタンスが作成されるたびに、クロージャが実行され、boardColors のデフォルト値が計算され、戻されます。上記の例のクロージャは temporaryBoard と言う一時的な配列で、ボード上の各正方形の適切な色を計算し、設定し、その設定が完了したら、クロージャの戻り値として、この一時的な配列を戻します。戻された配列の値は boardColors に格納され、squareIsBlackAt(row:column:) ユーティリティ関数で照会される事ができます。


  1. let board = Checkerboard()
  2. print(board.squareIsBlackAtRow(0, column: 1))
  3. // prints "true"
  4. print(board.squareIsBlackAtRow(9, column: 9))
  5. // prints "false"




前:継承 次:デイニシャライザ
目次
Xcode 9 の新機能

Swift:はじめに
Swift と Cocoa と Objective-C
Swift Blog より

  • ようこそ Swift へ(Part I)
  • Swift について
  • バージョン互換性
  • Swift のツアー
  • 単純な値
    制御フロー
    関数とクロージャ
    オブジェクトとクラス
    列挙型と構造体
    プロトコルと拡張機能
    エラー処理
    汎用(ジェネリック)
  • Swift 言語のガイド(Part II)
  • Swift の基本
  • 定数と変数
  • 定数と変数の宣言
    型注釈
    定数と変数の命名
    定数と変数の印刷
    コメント
    セミコロン
  • 整数
  • 整数の境界
    Int
    UInt
    浮動小数点数
    安全な型と型推論
    数値リテラル
  • 数値型変換
  • 整数変換
    整数と浮動小数点間の変換
    型エイリアス
    ブール型
    タプル
  • Optional
  • nil
    if 文と強制開封
    Optional の結合
    暗黙に開封された Optionals
    エラー処理
  • アサーション(断言)と前提条件
  • アサーションを使用したデバッグ
    前提条件の実施
  • 基本演算子
  • 専門用語
    代入演算子
  • 算術演算子
  • 剰余演算子
    単項マイナス演算子
    単項プラス演算子
    複合代入演算子
    比較演算子
    三項条件演算子
    Nil 合体演算子
  • 範囲演算子
  • 閉鎖範囲演算子
    半開放範囲演算子
    片方の範囲
  • 論理演算子
  • 論理 NOT 演算子
    論理 AND 演算子
    論理 OR 演算子
    論理演算子の組み合わせ
    明示的な括弧
  • 文字列と文字
  • 文字列リテラル
    複数行の文字列リテラル
    文字列リテラル内の特殊文字
    空の文字列の初期化
    文字列の可変性
    文字列は値の型
    文字を使った作業
    文字列と文字を連結
    文字列補間
  • ユニコード(Unicode)
  • Unicode スカラー
    文字列リテラルの中の特別の文字
    拡張書記クラスタ
    文字を数える
  • 文字列のアクセスと変更
  • 文字列のインデックス
    部分文字列
    挿入と削除
  • 文字列の比較
  • 文字列と文字の等価性
    接頭辞と接尾辞の等価性
  • 文字列の Unicode 表現
  • UTF-8 の表現
    UTF-16 表現
    Unicode のスカラー表現
  • コレクション型
  • コレクションの可変性
  • 配列
  • 配列型省略構文
    空の配列の作成
    デフォルト値を持つ配列の作成
    2つの配列を共にして一つの配列に
    配列リテラルでの配列の作成
    配列へのアクセスと変更
    配列の繰り返し処理
  • セット
  • セット型のハッシュ値
    セット型の構文
    空のセットの作成と初期化
    配列リテラルでセットの作成
    セットへのアクセスと変更
    セットを反復処理
  • セット操作の実行
  • 基本的なセットの操作
    セットの身分と等価性
  • Dictionary
  • Dictionary 型の省略型構文
    空の Dictionary を作成
    Dictionary リテラルで Dictionary の作成
    Dictionary のアクセスと変更
    Dictionary を繰り返し処理
  • フロー制御
  • For-In ループ
  • While ループ
  • While
    Repeat-While
  • 条件文
  • if 文
  • Switch
  • 暗黙の Fallthrough なし
    範囲の一致
    タプル(Tuples)
    値の結合
    Where
    複合した case
  • 制御転送文
  • Continue
  • Break
  • ループ文内の Break
    Switch 文内の Break
    Fallthrough
    ラベル付きの文
    早期終了
    API 利用可能性の確認
  • 関数
  • 関数の定義と呼び出し
  • 関数のパラメータと戻り値
  • パラメータなしの関数
    複数パラメータの関数
    戻り値なしの関数
    複数の戻り値を持つ関数
    optional のタプル型の戻り値
  • 関数引数のラベルとパラメータ名
  • 引数のラベルの指定
    引数ラベルの省略
    デフォルトのパラメータ値
    可変個引数のパラメータ
    In-Out パラメータ
  • 関数型
  • 関数型の使用
    パラメータ型としての関数型
    戻り値の型としての関数型
    入れ子になった関数
  • クロージャ
  • クロージャ式
  • ソートするメソッド
    クロージャ式の構文
    文脈から型を推論
    単一式クロージャからの暗黙的戻り値
    引数名の省略
    演算子メソッド
    後続クロージャ
    値のキャプチャ
    クロージャは参照型
    クロージャのエスケープ
    オートクロージャ
  • 列挙型
  • 列挙型の構文
    switch 文で列挙型の値の一致
    関連する値
  • 生の値
  • 暗黙に割り当てられた生の値
    生の値からの初期化
    再帰的な列挙型
  • クラスと構造体
  • クラスと構造体を比較
  • 定義の構文
    クラスと構造体のインスタンス
    プロパティにアクセス
    構造体型のためのメンバー化イニシャライザ
    構造体と列挙型は値型
  • クラスは参照型
  • ID 演算子
    ポインタ
    クラスと構造体の間の選択
    文字列、配列、辞書の代入とコピーの動作
  • プロパティ
  • 格納されたプロパティ
  • 定数構造体インスタンスの格納されたプロパティ
    遅延した格納されたプロパティ
    格納されたプロパティとインスタンス変数
  • 計算されたプロパティ
  • セッタ宣言の省略形
    読み取り専用の計算されたプロパティ
    プロパティ監視者
    グローバルとローカル変数
  • 型プロパティ
  • 型プロパティの構文
    型プロパティの照会と設定
  • メソッド
  • インスタンスメソッド
  • self プロパティ
    インスタンスメソッド内から値の型を変更
    変異メソッド内で self に代入
    型メソッド
  • サブスクリプト
  • サブスクリプトの構文
    サブスクリプトの使用法
    サブスクリプトのオプション
  • 継承
  • 基本クラスの定義
    サブクラス化
  • オーバーライド(上書き)
  • スーパークラスメソッド、プロパティ、サブスクリプトへのアクセス
    オーバーライドするメソッド
  • オーバーライドするプロパティ
  • プロパティのゲッタとセッタのオーバーライド
    プロパティ監視者のオーバーライド
    オーバーライドの防止
  • 初期化
  • 格納されたプロパティの初期値を設定
  • イニシャライザ
    デフォルトのプロパティ値
  • 初期化のカスタマイズ
  • 初期化パラメータ
    パラメータ名と引数ラベル
    引数ラベルのないイニシャライザのパラメータ
    Optional のプロパティ型
    初期化中に定数プロパティへの代入
  • デフォルトのイニシャライザ
  • 構造体型のためのメンバ化イニシャライザ
    値型のイニシャライザデリゲート
  • クラスの継承と初期化
  • 指定イニシャライザとコンビニエンスイニシャライザ
    指定とコンビニエンスイニシャライザの構文
    クラス型のイニシャライザデリゲート
    二相の初期化
    イニシャライザ継承とオーバーライド
    自動イニシャライザの継承
    実際の指定とコンビニエンスイニシャライザ
  • 失敗可能イニシャライザ
  • 生の値を持つ列挙型のための失敗可能イニシャライザ
    初期化失敗の伝播
    失敗可能イニシャライザのオーバーライド
    init! の失敗可能イニシャライザ
    必須イニシャライザ
    クロージャや関数でのデフォルトのプロパティ値設定
  • デイニシャライザ
  • デイニシャライザはどのように働くか
    作動中のデイニシャライザ
  • Optional の連鎖
  • 強制開封の代替としての Optional の連鎖
    Optional の連鎖のモデルクラスの定義
    Optional の連鎖を使用したプロパティへのアクセス
    Optional の連鎖を通じてメソッドを呼び出す
  • Optional の連鎖を通じてサブスクリプトへのアクセス
  • Optional 型のサブスクリプトにアクセス
    連鎖の複数レベルのリンク
    optional の戻り値を持つメソッドでの連鎖
  • エラー処理
  • エラーの表現と Throw
    エラーの処理
    throw 関数を使用したエラーの伝播
    Do-Catch を使用したエラー処理
    エラー をOptional の値に変換
    エラー伝播を無効に
    クリーンアップアクションの指定
  • 型キャスト
  • 型キャストのためのクラス階層の定義
    型のチェック
    ダウンキャスト
  • Any と AnyObjecgt 用の型キャスティング
  • ネストした型
  • 実際のネストした型
    ネストした型への参照
  • 拡張機能
  • 拡張機能の構文
    計算されたプロパティ
    イニシャライザ
  • メソッド
  • 変異インスタンスメソッド
    サブスクリプト
    ネストした型
  • プロトコル
  • プロトコルの構文
    プロパティの要件
    メソッドの要件
    変異メソッドの要件
  • イニシャライザの要件
  • プロトコルイニシャライザ要件のクラス実装
    失敗可能イニシャライザの要件
    型としてのプロトコル
    デリゲート
  • 拡張機能を持つプロトコル準拠の追加
  • 拡張機能を持つプロトコルの採用を宣言
    プロトコル型のコレクション
    プロトコルの継承
    クラス専用プロトコル
    プロトコルの構成
    プロトコル準拠の確認
    Optional のプロトコル要件
  • プロトコル拡張機能
  • デフォルトの実装の提供
    プロトコル拡張機能に制約を追加
  • ジェネリック(汎用)
  • 汎用が解決する問題
    汎用関数
    型パラメータ
    型パラメータの命名
    汎用の型
    汎用型の拡張
  • 型の制約
  • 型制約の構文
    実際の型の制約
  • 関連型
  • 実際の関連型
    既存の型を拡張して関連型を指定
    型注釈を使用して関連型を制約
    汎用の Where 句
    汎用の Where 句を含む拡張機能
    関連する型と汎用の Where 句
    汎用のサブスクリプト
  • 自動参照カウント
  • どのように ARC は働くか
    実際の ARC
    クラスインスタンス間の強い循環参照
  • クラスインスタンス間の強い循環参照の解決
  • 弱い参照
    所有されていない参照
    所有されていない参照と暗黙に開封された Optional のプロパティ
    クロージャの strong な循環参照
  • クロージャの strong な循環参照の解決
  • キャプチャリストの定義
    弱い参照と所有されていない参照
  • メモリの安全性
  • メモリへのアクセス競合の理解
    メモリアクセスの特徴
    In-Out パラメータへのアクセスの競合
    メソッド内の Self へのアクセスの競合
    プロパティへのアクセスの競合
  • アクセス制御
  • モジュールとソースファイル
  • アクセスレベル
  • アクセスレベルの全体的指針
    デフォルトのアクセスレベル
    ターゲット一つのアプリのアクセスレベル
    フレームワークのアクセスレベル
    ユニットテストのターゲット用のアクセスレベル
    アクセス制御の構文
  • カスタム型
  • タプル型
    関数型
  • 列挙型
  • 生の値と関連する値
    ネストした型
    サブクラス化
  • 定数、変数、プロパティ、およびサブスクリプト
  • ゲッタとセッタ
  • イニシャライザ
  • デフォルトのイニシャライザ
    構造体型用のデフォルトメンバ化イニシャライザ
  • プロトコル
  • プロトコルの継承
    プロトコルの準拠
  • 拡張機能
  • 拡張機能の private メンバ
    汎用
    型エイリアス
  • 高度な演算子
  • ビット単位演算子
  • ビット単位の NOT 演算子
    ビット単位の AND 演算子
    ビット単位の OR 演算子
    ビット単位の XOR 演算子
  • ビット単位の左と右シフト演算子
  • 符号なし整数のシフト動作
    符号付き整数のシフト動作
  • オーバーフロー演算子
  • 値オーバーフロー
    優先順位と結合性
  • 演算子メソッド
  • 接頭辞と接尾辞演算子
    複合代入演算子
    等価演算子
  • カスタム演算子
  • カスタム挿入辞演算子の優先順位
  • 言語のガイド(Part III)
  • 言語リファレンスについて
  • 文法の読み方
  • 語彙の構造
  • 空白とコメント
    識別子
    キーワードと句読点
  • リテラル
  • 整数リテラル
    浮動小数点リテラル
    文字列のリテラル
    演算子

  • 型注釈
    型識別子
    タプル型
    関数型
    エスケープしないクロージャの制限事項
    配列型
    辞書型
    Optional の型
    暗黙に開封された Optional の型
    プロトコル構成の型
    メタタイプ型
    型の継承句
    型の推測

  • 接頭辞式
    Try 演算子
  • 二項式
  • 代入演算子
    三項条件演算子
    型キャスト演算子
  • 一次式
  • リテラル式
    Self 式
    スーパークラス式
  • クロージャ式
  • キャプチャ・リスト
    暗黙のメンバ式
    括弧で囲まれた式
    タプル式
    ワイルドカード式
    キーパス式
    セレクタ式
    キーパス文字列式
  • 接尾辞の式
  • 関数呼び出し式
    イニシャライザ式
    明示的なメンバ式
    接尾辞の Self 式
    サブスクリプト 式
    強制値の式
    Optional の連鎖式

  • ループ文
  • For-In 文
    While 文
    Repeat-While 文
  • 分岐文
  • if 文
    Guard 文
  • switch 文
  • switch 文は、網羅的である必要あり
    実行が暗黙的に case を Fall Through しない
    ラベル付き文
  • 制御転送文
  • break 文
    continue 文
    fallthrough 文
    return 文
    throw 文
    defer 文
    do 文
  • コンパイラ制御文
  • 条件コンパイルブロック
    行制御文
    利用可能条件
  • 宣言
  • トップレベルのコード
    コードブロック
    Import 宣言
    ­定数の宣言
  • 変数の宣言
  • 格納された変数と格納された変数のプロパティ
    計算された変数と計算されたプロパティ
    格納された変数監視者とプロパティの監視者
    型変数プロパティ
    型エイリアス宣言
  • 関数の宣言
  • パラメータ名
    In-Out パラメータ
    パラメータの特殊な種類
    メソッドの特殊な種類
    Throw する関数とメソッド
    Rethrow する関数とメソッド
    決して返さない関数
  • 列挙型の宣言
  • 任意の型の case を列挙
  • 間接による列挙
    生の値型の case を列挙
    列挙型 case へのアクセス
    構造体の宣言
    クラスの宣言
  • プロトコルの宣言
  • プロトコル・プロパティ宣言
    プロトコル・メソッド宣言
    プロトコル・イニシャライザ宣言
    プロトコル・サブスクリプト宣言
    プロトコルに関連した型の宣言
  • イニシャライザ宣言
  • 失敗可能イニシャライザ
    デイニシャライザ宣言
    拡張機能の宣言
    サブスクリプト宣言
    演算子の宣言
    優先順位グループ宣言
  • 宣言修飾子
  • アクセス制御レベル
  • 属性
  • 宣言の属性
  • インターフェイスビルダーで使われる宣言属性
    型の属性
  • パターン
  • ワイルドカードパターン
    識別子パターン
    値結合パターン
    タプルパターン
    列挙型 case パターン
    Optional のパターン
    型キャストパターン
    式のパターン
  • 汎用パラメータと引数
  • 汎用パラメータ句
  • 汎用の where 句
    汎用引数句
  • 文法のまとめ
  • 語彙の構造



    宣言
    属性
    パターン
    汎用パラメータと引数
  • マニュアルの変更履歴
  • 変更履歴












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)












    トップへ(Swift Language Basics)