NOTE 格納プロパティにデフォルト値を割り当てるか、イニシャライザ内でその初期値を設定すると、プロパティオブザーバを呼び出さずに、そのプロパティに値が直接設定されます。
init
キーワードを使用して記述されます:Fahrenheit
という新しい構造体を定義しています。Fahrenheit
構造体には、Double
型の temperature
という 1 つの格納プロパティがあります。init
を定義します。これは、格納された温度を 32.0
(華氏での水の凝固点)の値で初期化します。NOTE プロパティが常に同じ初期値を取る場合は、イニシャライザ内で値を設定するのではなく、デフォルト値を指定します。最終結果は同じですが、デフォルト値の方がプロパティの初期化と宣言をより密接に結び付けています。これにより、イニシャライザが短く明確になり、デフォルト値からプロパティの型を推論できるようになります。また、デフォルト値を使用すると、この章で後述するように、デフォルトのイニシャライザとイニシャライザの継承を利用しやすくなります。
temperature
プロパティのデフォルト値を指定することにより、上記の Fahrenheit
構造体をよりシンプルな形式で書くことができます。Celsius
という構造体を定義しています。Celsius
構造体は、init(fromFahrenheit:)
および init(fromKelvin:)
という 2 つのカスタムイニシャライザを実装しています。これらは、構造体の新しいインスタンスを異なる温度スケールの値で初期化しています。fromFahrenheit
という引数ラベルと fahrenheit
というパラメータ名を持つ単一のパラメータがあります。2 番目のイニシャライザには、fromKelvin
という引数ラベルと kelvin
というパラメータ名を持つ単一のパラメータがあります。どちらのイニシャライザも、単一のパラメータを対応する摂氏の値に変換し、この値を temperatureInCelsius
というプロパティに格納しています。red
、green
、blue
という 3 つの定数プロパティを持つ Color
という構造体を定義しています。これらのプロパティには、色の赤、緑、青の量を示す 0.0
~ 1.0
の値が格納されます。Color
は、赤、緑、および青のコンポーネント用に Double
型の適切に名前が付けられた 3 つのパラメータを含むイニシャライザを提供します。Color
は、3 つ全ての色コンポーネントに同じ値を提供するために使用される、単一の white
パラメータを持つ 2 番目のイニシャライザも提供します。Color
インスタンスを作成できます。_
) を記述して、デフォルトの挙動をオーバーライドします。Celsius
の例の拡張バージョンで、すでに摂氏スケールにある Double
値から新しい Celsius
インスタンスを作成する追加のイニシャライザを備えています。Celsius(37.0)
は、意図が明確なので引数ラベルを必要としません。したがって、このイニシャライザを init(_ celsius: Double)
と記述して、名前のない Double
値を指定して呼び出すことができるのは妥当です。nil
で自動的に初期化されます。こうすることで、プロパティが初期化中に意図的に「まだ値がない」ことを示すことができます。SurveyQuestion
というクラスを定義し、オプショナルの String
プロパティとして response
を定義しています。String?
または Optional<String>
で宣言されています。SurveyQuestion
の新しいインスタンスが初期化されると、デフォルト値の nil
、つまり「文字列はまだありません」が自動的に割り当てられます。NOTE クラスインスタンスの場合、初期化中に定数プロパティを変更できるのは、それを導入したクラスだけです。サブクラスでは変更できません。
SurveyQuestion
の例を修正して、質問の text
プロパティに変数プロパティではなく定数プロパティを使用して、SurveyQuestion
のインスタンスが作成されたら質問が変更されないことを示すことができます。text
プロパティは定数ですが、クラスのイニシャライザ内で設定できます。ShoppingListItem
というクラスを定義しています。ShoppingListItem
クラスの全てのプロパティにはデフォルト値があり、スーパークラスを持たない基本クラスのため、ShoppingListItem
は、全てのプロパティにデフォルト値が設定された新しいインスタンスを作成するイニシャライザの実装を自動で獲得します(name
プロパティはオプショナルの String
プロパティのため、この値がコードに記述されていなくても、デフォルト値の nil
が自動的に設定されます)。上記の例では、ShoppingListItem
クラスのデフォルトイニシャライザを使用して ShoppingListItem()
と記述し、新しいインスタンスを作成して item
という変数に割り当てています。width
と height
という 2 つのプロパティを持つ Size
という構造体を定義しています。両方のプロパティは、デフォルト値 0.0
を割り当てることにより、Double
型だと推論されます。Size
構造体は、新しい Size
インスタンスを初期化するために使用できるメンバワイズイニシャライザ init(width:height:)
が自動的に定義されています。Size
構造体の height
と width
の両方のプロパティにデフォルト値があります。プロパティのいずれかまたは両方を省略できます。イニシャライザは、省略した全てのプロパティにデフォルト値を使用します。例えば、次のようになります:self.init
を使用して同じ値型から他のイニシャライザを参照します。self.init
は、イニシャライザ内からのみ呼び出すことができます。NOTE カスタムの値型をデフォルトイニシャライザとメンバワイズイニシャライザ、および独自のカスタムイニシャライザで初期化できるようにする場合は、値型の元の実装の一部としてではなく、extension にカスタムイニシャライザを記述します。詳細については、Extension(拡張)を参照ください。
Rect
構造体を定義しています。この例では、Size
と Point
という 2 つの補助となる構造体が必要です。どちらも、全てのプロパティにデフォルト値 0.0
を提供します:Rect
構造体を初期化できます。つまり、0
で初期化されたデフォルトの origin
と size
のプロパティ値を使用するか、特定の原点とサイズを指定するか、特定の中心点とサイズを指定します。これらの初期化の選択肢は、Rect
構造体の定義の一部として 3 つのカスタムイニシャライザで表されます:Rect
イニシャライザ init()
は、独自のカスタムイニシャライザがない場合に受け取るデフォルトのイニシャライザと機能的に同じです。このイニシャライザには、空の中括弧 {}
のペアで表される空の本文があります。このイニシャライザを呼び出すと、原点とサイズのプロパティが両方ともプロパティ定義の Point(x: 0.0, y: 0.0)
と Size(width: 0.0, height: 0.0)
のデフォルト値で初期化された Rect
インスタンスが返されます:Rect
イニシャライザ init(origin:size:)
は、独自のカスタムイニシャライザがない場合に構造体に自動で定義されるメンバワイズイニシャライザと機能的に同じです。このイニシャライザは、単に origin
および size
引数の値を適切な格納されたプロパティに割り当てます:Rect
イニシャライザ init(center:size:)
は、もう少し複雑です。center
と size
値に基づいて適切な原点を計算することから始めます。次に、init(origin:size:)
イニシャライザを呼び出し(委譲)します。このイニシャライザは、適切なプロパティに新しい原点とサイズの値を保存します。init(center:size:)
イニシャライザを使っても、origin
と size
の新しい値を適切なプロパティに割り当てることができます。ただし、init(center:size:)
イニシャライザは、適切な機能をすでに提供している既存のイニシャライザを利用する方が便利(そして意図がより明確)です。init
キーワードの前にスペース区切りで covenience
修飾子を配置します:NOTE これらのルールは、クラスのユーザが各クラスのインスタンスを作成する方法には影響しません。上の図の全てのイニシャライザを使用して、それらが属するクラスの完全に初期化されたインスタンスを作成できます。ルールは、クラスのイニシャライザの実装の記述方法にのみ影響します。
NOTE Swift の 2 段階の初期化プロセスは、Objective-C の初期化に似ています。主な違いは、第 1 段階では、Objective-C がゼロまたはヌル値 (0
やnil
など) を全てのプロパティに割り当てることです。Swift の初期化フローは、カスタムの初期値を設定できるという点でより柔軟であり、0
またはnil
が有効なデフォルト値ではない型に対処できます。
self
にアクセスして、そのプロパティを変更したり、インスタンスメソッドを呼び出したりできるようになりましたself
を操作することができるようになりますNOTE スーパークラスのイニシャライザは特定の状況で継承できますが、安全で適切な場合に限ります。詳細については、以下のAutomatic Initializer Inheritance(自動イニシャライザの継承)を参照してください。
override
修飾子を記述する必要があります。Default Initializers(デフォルトイニシャライザ)で説明されているように、これは、自動的に提供されるデフォルトのイニシャライザをオーバーライドする場合にも当てはまります。override
修飾子が存在すると、Swift は、スーパークラスにオーバーライドされる指定イニシャライザがあるかどうかを確認し、オーバーライドするイニシャライザのパラメータが意図したとおりの形になっていることを検証します。NOTE サブクラスのイニシャライザの実装が convenience イニシャライザであっても、スーパークラスで指定イニシャライザをオーバーライドするときは、常にoverride
修飾子を記述します。
override
修飾子を記述しません。Vehicle
という基本クラスを定義しています。この基本クラスは、デフォルトの Int
値が 0 の numberOfWheels
という格納プロパティを宣言しています。numberOfWheels
プロパティは、description
という計算プロパティで使用され、乗り物の特性を説明しています:Vehicle
クラスは、その唯一の格納プロパティにデフォルト値を提供し、カスタムのイニシャライザを提供していません。その結果、Default Initializers(デフォルトイニシャライザ)で説明されているように、デフォルトのイニシャライザを自動的に受け取ります。デフォルトイニシャライザは、(使用可能な場合)常にクラスの指定イニシャライザで、numberOfWheels
が 0
の新しい Vehicle
インスタンスを作成するために使用できます:Bicycle
という Vehicle
のサブクラスを定義しています:Bicycle
サブクラスは、カスタムの指定イニシャライザ init()
を定義します。この指定イニシャライザは Bicycle
のスーパークラスの指定イニシャライザと一致するため、Bicycle
では override
修飾子でマークされています。Bicycle
の init()
イニシャライザは、最初に super.init()
を呼び出します。これは、Bicycle
クラスのスーパークラスの Vehicle
のデフォルトのイニシャライザを呼び出します。これにより、Bicycle
がプロパティを変更する前に、継承したプロパティ numberOfWheels
が Vehicle
によって初期化されます。super.init()
を呼び出した後、numberOfWheels
の値は新しい値 2
に置き換えられます。Bicycle
のインスタンスを作成する場合、継承した description
計算プロパティを呼び出して、numberOfWheels
プロパティがどのように更新されたかを確認できます:super.init()
の呼び出しを省略できます。Hoverboard
と呼ばれる Vehicle
の別のサブクラスを定義しています。イニシャライザでは、Hoverboard
クラスはその color
プロパティのみを設定します。このイニシャライザは、super.init()
を明示的に呼び出す代わりに、スーパークラスのイニシャライザを暗黙的に呼び出してプロセスを完了しています。Hoverboard
のインスタンスは、Vehicle
イニシャライザによって提供されるデフォルトのホイール数を使用します。NOTE サブクラスは、初期化中に継承した変数プロパティを変更できますが、継承した定数プロパティを変更することはできません。
NOTE サブクラスは、ルール 2 を満たす方法の 1 つとして、スーパークラスの指定イニシャライザをサブクラスの convenience イニシャライザとして実装できます。
Food
、RecipeIngredient
、および ShoppingListItem
という 3 つのクラスの階層を定義し、それらのイニシャライザがどのように相互作用するかを示しています。Food
と呼ばれ、食品の名前をカプセル化するシンプルなクラスです。Food
クラスは、name
という単一の String
プロパティを宣言し、Food
インスタンスを作成するために 2 つのイニシャライザを提供します。Food
クラスのイニシャライザのチェーンを示しています。Food
クラスは、name
という単一の引数を受け取る指定イニシャライザを提供します。このイニシャライザを使用して、特定の名前で新しい Food
インスタンスを作成できます。Food
クラスの init(name: String)
イニシャライザは、指定イニシャライザとして提供されています。これは、新しい Food
インスタンスの全ての格納プロパティが完全に初期化されていることを保証するためです。Food
クラスにはスーパークラスがないため、init(name: String)
イニシャライザは、初期化を完了するために super.init()
を呼び出す必要はありません。Food
クラスは、引数のない convenience イニシャライザ init()
も提供します。init()
イニシャライザは、[Unnamed]
のという name
の値を使って Food
クラスの init(name: String)
に委譲することで、新しい食品にデフォルトのプレースホルダ名を提供します。RecipeIngredient
と呼ばれる Food
のサブクラスです。RecipeIngredient
クラスは、料理レシピの材料をモデル化しています。これは、(Food
から継承する name
プロパティに加えて) amount
という Int
プロパティを宣言し、RecipeIngredient
インスタンスを作成するための 2 つのイニシャライザを提供します。RecipeIngredient
クラスのイニシャライザのチェーンを示しています。RecipeIngredient
クラスには、単一の指定イニシャライザ init(name: String, amount: Int)
があり、これを使用して新しい RecipeIngredient
インスタンスの全てのプロパティを設定できます。このイニシャライザは、渡された quantity
引数を quantity
プロパティに割り当てることから開始します。これは、RecipeIngredient
で定義された唯一の新しいプロパティです。その後、イニシャライザは Food
クラスの init(name: String)
イニシャライザに委譲します。このプロセスは、上記のTwo-Phase Initialization(2 段階の初期化)の初期化の安全チェック 1 を満たしています。RecipeIngredient
は、名前だけで RecipeIngredient
インスタンスを作成する convenience イニシャライザ init(name: String)
も定義します。この convenience イニシャライザは、数量を 1
と想定して、明示的に数量を指定せずに RecipeIngredient
インスタンスを作成します。この convenience イニシャライザの定義により、RecipeIngredient
インスタンスの作成がより迅速かつ便利になり、単一量の RecipeIngredient
インスタンスを複数作成する際にコードの重複が回避できます。この convenience イニシャライザは、単にクラスの指定イニシャライザに委譲し、quantity
に 1
を渡します。RecipeIngredient
によって提供される init(name: String)
convenience イニシャライザは、Food
の init(name: String)
指定イニシャライザと同じパラメータを受け取ります。つまり、この convenience イニシャライザはスーパークラスから指定イニシャライザをオーバーライドするため、override
修飾子を付ける必要があります(Initializer Inheritance and Overriding(イニシャライザの継承とオーバーライド)を参照)。RecipeIngredient
は、convenience イニシャライザとして init(name: String)
イニシャライザを提供していますが、さらにそのスーパークラスの指定イニシャライザの全ての実装を提供しています。したがって、RecipeIngredient
は、そのスーパークラスの convenience イニシャライザも全て自動的に継承します。RecipeIngredient
のスーパークラスは Food
で、init()
という名前の convenience イニシャライザが 1 つあります。したがって、このイニシャライザは RecipeIngredient
に継承されます。継承されたバージョンの init()
は、Food
バージョンではなく RecipeIngredient
バージョンの init(name:String)
に委譲することを除いて、Food
バージョンとまったく同じように機能します。RecipeIngredient
インスタンスを作成できます:ShoppingListItem
と呼ばれる RecipeIngredient
のサブクラスです。ShoppingListItem
クラスは、ショッピングリストに表示されるレシピの材料をモデル化しています。ShoppingListItem
には、purchased
という Bool
型プロパティが導入されており、デフォルト値は false
です。ShoppingListItem
は、インスタンスの説明をする description
という計算プロパティも追加しています。NOTEShoppingListItem
は、purchased
の初期値を提供するイニシャライザを定義しません。これは、(ここでモデル化されている)ショッピングリスト内のアイテムは常に未購入から始まるためです。
ShoppingListItem
は全ての指定イニシャライザと convenience イニシャライザをスーパークラスから自動的に継承します。ShoppingListItem
インスタンスを作成できます。ShoppingListItem
インスタンスを含む配列リテラルから、breakfastList
という新しい配列が作成されます。配列の型は [ShoppingListItem]
だと推論されます。配列が作成された後、配列の先頭にある ShoppingListItem
の名前が "[Unnamed]"
から "Orange juice"
に変更され、購入済みとしてマークされます。配列内の各アイテムの説明を出力すると、デフォルトの状態が期待どおりに設定されていることがわかります。init
キーワードの後に疑問符を置いて、失敗するイニシャライザを記述します(init?
)。NOTE 同じパラメータの型と名前で失敗可能イニシャライザと失敗しないイニシャライザを定義することはできません。
return nil
を記述します。NOTE 厳密に言えば、イニシャライザは値を返しません。むしろ、その役割は、初期化が終了するまでに自分自身が完全かつ正しく初期化されることを保証することです。初期化に失敗した場合return nil
を記述しますが、初期化の成功を示すためにreturn
キーワードを使用することはありません。
init(exactly:)
イニシャライザを使用します。型変換で値を維持できない場合、イニシャライザは失敗します:Animal
と呼ばれる構造体を定義し、species
と呼ばれる String
の定数プロパティを使用しています。Animal
構造体は、species
と呼ばれる単一のパラメータを持つ失敗可能イニシャライザも定義します。このイニシャライザは、イニシャライザに渡された species
の値が空の文字列かどうかをチェックします。空の文字列が見つかった場合、初期化に失敗します。それ以外の場合、species
のプロパティの値が設定され、初期化が成功します:Animal
インスタンスの初期化を試み、初期化が成功したかどうかを確認できます:species
パラメータに渡すと、イニシャライザは初期化に失敗します:NOTE 空の文字列 ("Giraffe" ではなく "" など) のチェックは、オプショナルの String 値がないことを示すnil
のチェックとは異なります。上記の例では、空の文字列 ("") は妥当な非 オプショナルの文字列です。ただし、Animal
がそのspecies
プロパティの値として空の文字列を持つことは適切ではありません。この制限をモデル化するために、空の文字列が見つかった場合、失敗可能イニシャライザは初期化に失敗します。
kelvin
、celsius
、fahrenheit
)を使用して、TemperatureUnit
という列挙型を定義しています。温度記号を表す Character
値の適切な列挙ケースを見つけるために、失敗可能イニシャライザが使用されます:rawValue
と呼ばれるパラメータを受け取り、一致する列挙ケースが見つかった場合はそれを選択するか、一致する値がない場合は初期化に失敗する失敗可能イニシャライザ init?(rawValue:)
を自動的に生成します。TemperatureUnit
の例を書き直して、Character
型の Raw Value を使用し、init?(rawValue:)
イニシャライザを利用できます:NOTE 失敗可能イニシャライザから失敗しないイニシャライザに委譲することもできます。他の方法では失敗しない既存の初期化プロセスに失敗する可能性を追加する必要がある場合は、このアプローチを使用します。
CartItem
という Product
のサブクラスを定義しています。CartItem
クラスは、オンラインショッピングカート内のアイテムをモデル化しています。CartItem
は、quantity
と呼ばれる定数格納プロパティを導入し、このプロパティが常に少なくとも 1
の値を持つようにします:CartItem
の失敗可能イニシャライザは、1
以上の quantity
の値を受け取ったかどうかを検証することから始まります。quantity
が無効な場合、初期化プロセス全体はすぐに失敗し、それ以上の初期化コードは実行されません。同様に、Product
の失敗可能イニシャライザは name
の値をチェックし、name
が空の文字列の場合、初期化プロセスはすぐに失敗します。name
が空でなく、quantity
が 1
以上の CartItem
インスタンスを作成すると、初期化は成功します:quantity
の値が 0
の CartItem
インスタンスを作成しようとすると、CartItem
のイニシャライザによって初期化が失敗します:name
の値が空の CartItem
インスタンスを作成しようとすると、スーパークラスの Product
イニシャライザによって初期化が失敗します。NOTE 失敗可能イニシャライザを失敗しないイニシャライザでオーバーライドすることはできますが、その逆はできません。
Document
というクラスを定義しています。このクラスは、空ではない文字列値または nil
のいずれかが可能ですが、空文字列にすることはできない name
プロパティで初期化できるドキュメントをモデル化しています。AutomaticallyNamedDocument
という Document
のサブクラスを定義しています。AutomaticNamedDocument
サブクラスは、Document
の指定イニシャライザの両方をオーバーライドします。これらのオーバーライドにより、インスタンスが名前なしで初期化された場合、または空の文字列が init(name:)
イニシャライザに渡された場合に、AutomaticallyNamedDocument
インスタンスは "[Untitled]"
をname
の初期値として持つことが保証されます。AutomaticNamedDocument
は、スーパークラスの失敗可能イニシャライザ(init?(name:)
)を、失敗しないイニシャライザ(init(name:)
)でオーバーライドします。AutomaticNamedDocument
は、スーパークラスとは異なる方法で空の文字列に対処するため、イニシャライザは失敗することがなく、代わりに失敗しないバージョンのイニシャライザを提供します。UntitledDocument
サブクラスは常に "[Untitled]"
という名前で、初期化中にスーパークラスの失敗可能イニシャライザ(init(name:)
)を使用します:init(name:)
イニシャライザが名前に空の文字列を指定して呼び出された場合、強制アンラップにより実行時エラーが発生しますが、文字列定数で呼び出されているため、イニシャライザが失敗しないことがわかり、この場合は実行時エラーは発生しません。init
キーワードの後に疑問符(?
)を配置して(init?
)、適切な型のオプショナルのインスタンスを作成する失敗可能イニシャライザを定義します。または、適切な型へ暗黙的にアンラップしてオプショナルのインスタンスを作成する失敗可能イニシャライザを定義することもできます。これを行うには、疑問符の代わりに init
キーワードの後に感嘆符(!
)を置きます(init!
)。init?
から init!
へ委譲でき、その逆も可能です。また、init!
で init?
をオーバーライドでき、その逆も可能です。init
から init!
に委譲することもできますが、init!
の初期化が失敗した場合は、アサーションを引き起こします。required
修飾子を記述します。required
修飾子を記述して、イニシャライザの必須要件が初期化チェーン内の他のサブクラスに適用されることを示す必要があります。必須指定イニシャライザをオーバーライドするときは、override
修飾子を記述しません:NOTE 継承したイニシャライザで要件を満たすことができる場合、必須イニシャライザの明示的な実装を提供する必要はありません。
}
)の後に空の括弧(()
)が続いていることに注目してください。これは Swift にクロージャをすぐに実行するように指示します。これらの括弧を省略すると、クロージャの戻り値ではなく、クロージャ自体をプロパティに割り当てようとします。NOTE クロージャを使用してプロパティを初期化する場合、残りのインスタンスはクロージャが実行された時点ではまだ初期化されていないことに注意してください。つまり、たとえプロパティにデフォルト値があっても、クロージャ内から他のプロパティ値にアクセスできないことを意味します。また、暗黙的なself
プロパティを使用したり、インスタンスのメソッドを呼び出すこともできません。
Chessboard
という構造体を定義しています。チェスは 8 x 8
の盤上で、白と黒の正方形が交互に並んでいます。Chessboard
構造体には、boardColors
という 1 つのプロパティがあり、これは 64 の Bool
値の配列です。配列内の true
の値は黒い正方形を表し、false
の値は白い正方形を表します。配列の最初のアイテムはボードの左上の正方形を表し、配列の最後のアイテムはボードの右下の正方形を表します。boardColors
配列は、色の値を設定するためのクロージャで初期化されています。