初期化
日本語を消す 英語を消す下記URLから引用し、日本語訳をつけてみました。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/initialization
Set the initial values for a type’s stored properties and perform one-time setup.
型の保存されたプロパティの初期値を設定し、1 回限りのセットアップを実行します。
Initialization is the process of preparing an instance of a class, structure, or enumeration for use. This process involves setting an initial value for each stored property on that instance and performing any other setup or initialization that’s required before the new instance is ready for use.
初期化は、クラス、構造体、または列挙型のインスタンスを使用できるように準備するプロセスです。 このプロセスには、そのインスタンスに保存されている各プロパティの初期値の設定と、新しいインスタンスを使用できるようになる前に必要なその他のセットアップまたは初期化の実行が含まれます。
You implement this initialization process by defining initializers, which are like special methods that can be called to create a new instance of a particular type. Unlike Objective-C initializers, Swift initializers don’t return a value. Their primary role is to ensure that new instances of a type are correctly initialized before they’re used for the first time.
この初期化プロセスを実装するには、イニシャライザを定義します。イニシャライザは、特定の型の新しいインスタンスを作成するために呼び出すことができる特別なメソッドのようなものです。 Objective-C イニシャライザとは異なり、Swift イニシャライザは値を返しません。 これらの主な役割は、型の新しいインスタンスが初めて使用される前に正しく初期化されていることを確認することです。
Instances of class types can also implement a deinitializer, which performs any custom cleanup just before an instance of that class is deallocated. For more information about deinitializers, see Deinitialization.
クラス型のインスタンスは、そのクラスのインスタンスの割り当てが解除される直前にカスタム クリーンアップを実行する初期化解除機能を実装することもできます。 初期化解除子の詳細については、「初期化解除」を参照してください。
Setting Initial Values for Stored Properties
保存されたプロパティの初期値の設定
Classes and structures must set all of their stored properties to an appropriate initial value by the time an instance of that class or structure is created. Stored properties can’t be left in an indeterminate state.
クラスと構造体は、そのクラスまたは構造体のインスタンスが作成されるまでに、保存されているすべてのプロパティを適切な初期値に設定する必要があります。 保存されたプロパティを不確定な状態のままにすることはできません。
You can set an initial value for a stored property within an initializer, or by assigning a default property value as part of the property’s definition. These actions are described in the following sections.
保存されたプロパティの初期値は、イニシャライザ内で設定することも、プロパティの定義の一部としてデフォルトのプロパティ値を割り当てることによっても設定できます。 これらのアクションについては、次のセクションで説明します。
Note
注釈
When you assign a default value to a stored property, or set its initial value within an initializer, the value of that property is set directly, without calling any property observers.
格納されたプロパティにデフォルト値を割り当てるか、イニシャライザ内でその初期値を設定すると、プロパティ オブザーバーを呼び出さずに、そのプロパティの値が直接設定されます。
Initializers
初期化子
Initializers are called to create a new instance of a particular type. In its simplest form, an initializer is like an instance method with no parameters, written using the init
keyword:
イニシャライザは、特定の型の新しいインスタンスを作成するために呼び出されます。 最も単純な形式では、イニシャライザはパラメータのないインスタンス メソッドのようなもので、init
キーワードを使用して記述されます。
init() {
// perform some initialization here
}
The example below defines a new structure called Fahrenheit
to store temperatures expressed in the Fahrenheit scale. The Fahrenheit
structure has one stored property, temperature
, which is of type Double
:
以下の例では、華氏スケールで表現された温度を保存するために、Fahrenheit
という新しい構造体を定義しています。 Fahrenheit
構造には、Double
型の保存プロパティであるtemperature
が 1 つあります。
struct Fahrenheit {
var temperature: Double
init() {
temperature = 32.0
}
}
var f = Fahrenheit()
print("The default temperature is \(f.temperature)° Fahrenheit")
// Prints "The default temperature is 32.0° Fahrenheit"
The structure defines a single initializer, init
, with no parameters, which initializes the stored temperature with a value of 32.0
(the freezing point of water in degrees Fahrenheit).
この構造体は、パラメーターなしで単一の初期化子 init
を定義し、保存された温度を値 32.0
(華氏度における水の凝固点 ) で初期化します。
Default Property Values
デフォルトのプロパティ値
You can set the initial value of a stored property from within an initializer, as shown above. Alternatively, specify a default property value as part of the property’s declaration. You specify a default property value by assigning an initial value to the property when it’s defined.
上に示したように、保存されたプロパティの初期値をイニシャライザ内から設定できます。 あるいは、プロパティの宣言の一部としてデフォルトのプロパティ値を指定します。 デフォルトのプロパティ値を指定するには、プロパティの定義時に初期値を割り当てます。
Note
注釈
If a property always takes the same initial value, provide a default value rather than setting a value within an initializer. The end result is the same, but the default value ties the property’s initialization more closely to its declaration. It makes for shorter, clearer initializers and enables you to infer the type of the property from its default value. The default value also makes it easier for you to take advantage of default initializers and initializer inheritance, as described later in this chapter.
プロパティが常に同じ初期値を取る場合は、イニシャライザ内で値を設定するのではなく、デフォルト値を指定します。 最終結果は同じですが、デフォルト値はプロパティの初期化をその宣言により密接に結び付けます。 これにより、初期化子がより短く明確になり、デフォルト値からプロパティの型を推測できるようになります。 また、デフォルト値を使用すると、この章で後述するように、デフォルトのイニシャライザとイニシャライザの継承を利用しやすくなります。
You can write the Fahrenheit
structure from above in a simpler form by providing a default value for its temperature
property at the point that the property is declared:
プロパティが宣言される時点でそのtemperature
プロパティのデフォルト値を指定することで、上記のFahrenheit
構造をより簡単な形式で記述することができます。
struct Fahrenheit {
var temperature = 32.0
}
Customizing Initialization
初期化のカスタマイズ
You can customize the initialization process with input parameters and optional property types, or by assigning constant properties during initialization, as described in the following sections.
次のセクションで説明するように、入力パラメータとオプションのプロパティ 型を使用するか、初期化中に定数プロパティを割り当てることによって、初期化プロセスをカスタマイズできます。
Initialization Parameters
初期化パラメータ
You can provide initialization parameters as part of an initializer’s definition, to define the types and names of values that customize the initialization process. Initialization parameters have the same capabilities and syntax as function and method parameters.
イニシャライザの定義の一部として初期化パラメータを指定して、初期化プロセスをカスタマイズする値の型と名前を定義できます。 初期化パラメータの機能と構文は、関数およびメソッドのパラメータと同じです。
The following example defines a structure called Celsius
, which stores temperatures expressed in degrees Celsius. The Celsius
structure implements two custom initializers called init(fromFahrenheit:)
and init(fromKelvin:)
, which initialize a new instance of the structure with a value from a different temperature scale:
次の例では、摂氏で表される温度を保存する Celsius
という構造体を定義します。 Celsius
構造体は、init(fromFahrenheit:)
と init(fromKelvin:)
という 2 つのカスタム初期化子を実装しており、異なる温度スケールの値で構造体の新しいインスタンスを初期化します。
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
}
let boilingPointOfWater = Celsius(fromFahrenheit: 212.0)
// boilingPointOfWater.temperatureInCelsius is 100.0
let freezingPointOfWater = Celsius(fromKelvin: 273.15)
// freezingPointOfWater.temperatureInCelsius is 0.0
The first initializer has a single initialization parameter with an argument label of fromFahrenheit
and a parameter name of fahrenheit
. The second initializer has a single initialization parameter with an argument label of fromKelvin
and a parameter name of kelvin
. Both initializers convert their single argument into the corresponding Celsius value and store this value in a property called temperatureInCelsius
.
最初のイニシャライザには、引数ラベル fromFahrenheit
とパラメータ名 fahrenheit
を持つ単一の初期化パラメータがあります。 2 番目のイニシャライザには、引数ラベル fromKelvin
とパラメータ名 kelvin
を持つ単一の初期化パラメータがあります。 どちらのイニシャライザも、単一の引数を対応する摂氏の値に変換し、この値をtemperatureInCelsius
というプロパティに保存します。
Parameter Names and Argument Labels
パラメータ名と引数ラベル
As with function and method parameters, initialization parameters can have both a parameter name for use within the initializer’s body and an argument label for use when calling the initializer.
関数およびメソッドのパラメーターと同様、初期化パラメーターには、イニシャライザーの本体内で使用するパラメーター名と、イニシャライザーの呼び出し時に使用する引数ラベルの両方を含めることができます。
However, initializers don’t have an identifying function name before their parentheses in the way that functions and methods do. Therefore, the names and types of an initializer’s parameters play a particularly important role in identifying which initializer should be called. Because of this, Swift provides an automatic argument label for every parameter in an initializer if you don’t provide one.
ただし、初期化子には、関数やメソッドのように括弧の前に識別関数名がありません。 したがって、イニシャライザのパラメータの名前と型は、どのイニシャライザを呼び出すかを識別する際に特に重要な役割を果たします。 このため、引数ラベルを指定しない場合、Swift はイニシャライザ内のすべてのパラメータに自動引数ラベルを提供します。
The following example defines a structure called Color
, with three constant properties called red
, green
, and blue
. These properties store a value between 0.0
and 1.0
to indicate the amount of red, green, and blue in the color.
次の例では、red
、green
、blue
という 3 つの定数プロパティを持つ Color
という構造体を定義しています。 これらのプロパティには、色の赤、緑、青の量を示す 0.0
から 1.0
までの値が保存されます。
Color
provides an initializer with three appropriately named parameters of type Double
for its red, green, and blue components. Color
also provides a second initializer with a single white
parameter, which is used to provide the same value for all three color components.
Color
は、赤、緑、青のコンポーネントに対して Double
型の 3 つの適切な名前のパラメータを備えたイニシャライザを提供します。 Color
は、単一のwhite
パラメータを持つ 2 番目の初期化子も提供します。これは、3 つの色コンポーネントすべてに同じ値を提供するために使用されます。
struct Color {
let red, green, blue: Double
init(red: Double, green: Double, blue: Double) {
self.red = red
self.green = green
self.blue = blue
}
init(white: Double) {
red = white
green = white
blue = white
}
}
Both initializers can be used to create a new Color
instance, by providing named values for each initializer parameter:
どちらのイニシャライザも、各イニシャライザ パラメータに名前付きの値を指定することで、新しい Color
インスタンスを作成するために使用できます。
let magenta = Color(red: 1.0, green: 0.0, blue: 1.0)
let halfGray = Color(white: 0.5)
Note that it isn’t possible to call these initializers without using argument labels. Argument labels must always be used in an initializer if they’re defined, and omitting them is a compile-time error:
引数ラベルを使用せずにこれらのイニシャライザを呼び出すことはできないことに注意してください。 引数ラベルが定義されている場合は、常に初期化子で使用する必要があり、省略するとコンパイル時エラーが発生します。
let veryGreen = Color(0.0, 1.0, 0.0)
// this reports a compile-time error - argument labels are required
Initializer Parameters Without Argument Labels
引数ラベルのない初期化パラメータ
If you don’t want to use an argument label for an initializer parameter, write an underscore (_
) instead of an explicit argument label for that parameter to override the default behavior.
初期化パラメータに引数ラベルを使用したくない場合は、そのパラメータに明示的な引数ラベルの代わりにアンダースコア (_
) を記述して、デフォルトの動作をオーバーライドします。
Here’s an expanded version of the Celsius
example from Initialization Parameters above, with an additional initializer to create a new Celsius
instance from a Double
value that’s already in the Celsius scale:
以下は、上記の初期化パラメータのCelsius
の例の拡張バージョンで、すでに摂氏スケールにある Double
値から新しいCelsius
インスタンスを作成する追加のイニシャライザが含まれています。
struct Celsius {
var temperatureInCelsius: Double
init(fromFahrenheit fahrenheit: Double) {
temperatureInCelsius = (fahrenheit - 32.0) / 1.8
}
init(fromKelvin kelvin: Double) {
temperatureInCelsius = kelvin - 273.15
}
init(_ celsius: Double) {
temperatureInCelsius = celsius
}
}
let bodyTemperature = Celsius(37.0)
// bodyTemperature.temperatureInCelsius is 37.0
The initializer call Celsius(37.0)
is clear in its intent without the need for an argument label. It’s therefore appropriate to write this initializer as init(_ celsius: Double)
so that it can be called by providing an unnamed Double
value.
イニシャライザ呼び出し Celsius(37.0)
は、引数ラベルを必要とせずに、その意図が明確です。 したがって、名前のない Double
値を指定して呼び出せるように、このイニシャライザを init(_ celsius: Double)
として記述するのが適切です。
Optional Property Types
オプションのプロパティの種類
If your custom type has a stored property that’s logically allowed to have “no value” — perhaps because its value can’t be set during initialization, or because it’s allowed to have “no value” at some later point — declare the property with an optional type. Properties of optional type are automatically initialized with a value of nil
, indicating that the property is deliberately intended to have “no value yet” during initialization.
カスタム型に論理的に「値なし」が許可されている格納プロパティがある場合、おそらく初期化中にその値を設定できないため、または後で「値なし」にすることが許可されているため、そのプロパティを次のように宣言します ( オプションの型と宣言します)。 オプションの型のプロパティは値 nil
で自動的に初期化されます。これは、初期化中にプロパティが意図的に「まだ値を持たない」ように意図されていることを示します。
The following example defines a class called SurveyQuestion
, with an optional String
property called response
:
次の例では、SurveyQuestion
というクラスと、response
というオプションの String
プロパティを定義しています。
class SurveyQuestion {
var text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
// Prints "Do you like cheese?"
cheeseQuestion.response = "Yes, I do like cheese."
The response to a survey question can’t be known until it’s asked, and so the response
property is declared with a type of String?
, or “optional String
”. It’s automatically assigned a default value of nil
, meaning “no string yet”, when a new instance of SurveyQuestion
is initialized.
アンケートの質問に対する回答は質問されるまで分からないため、回答プロパティは String?
または「オプションの String
」の型で宣言されます。 SurveyQuestion
の新しいインスタンスが初期化されると、「まだ文字列が存在しない」ことを意味するデフォルト値 nil
が自動的に割り当てられます。
Assigning Constant Properties During Initialization
初期化中の定数プロパティの割り当て
You can assign a value to a constant property at any point during initialization, as long as it’s set to a definite value by the time initialization finishes. Once a constant property is assigned a value, it can’t be further modified.
初期化が終了するまでに定数プロパティが明確な値に設定されていれば、初期化中のどの時点でも定数プロパティに値を割り当てることができます。 定数プロパティに値が割り当てられると、それ以上変更することはできません。
Note
注釈
For class instances, a constant property can be modified during initialization only by the class that introduces it. It can’t be modified by a subclass.
クラス インスタンスの場合、定数プロパティは、それを導入したクラスによってのみ初期化中に変更できます。 サブクラスによって変更することはできません。
You can revise the SurveyQuestion
example from above to use a constant property rather than a variable property for the text
property of the question, to indicate that the question doesn’t change once an instance of SurveyQuestion
is created. Even though the text
property is now a constant, it can still be set within the class’s initializer:
上記の SurveyQuestion
の例を修正して、質問のtext
プロパティに変数プロパティではなく定数プロパティを使用し、SurveyQuestion
のインスタンスが作成されると質問が変更されないことを示すことができます。 text
プロパティは定数になりましたが、引き続きクラスのイニシャライザ内で設定できます。
class SurveyQuestion {
let text: String
var response: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}
let beetsQuestion = SurveyQuestion(text: "How about beets?")
beetsQuestion.ask()
// Prints "How about beets?"
beetsQuestion.response = "I also like beets. (But not with cheese.)"
Default Initializers
デフォルトのイニシャライザ
Swift provides a default initializer for any structure or class that provides default values for all of its properties and doesn’t provide at least one initializer itself. The default initializer simply creates a new instance with all of its properties set to their default values.
Swift は、すべてのプロパティにデフォルト値を提供する構造またはクラスに対してデフォルトのイニシャライザを提供し、それ自体は 1 つもイニシャライザを提供しません。 デフォルトのイニシャライザは、すべてのプロパティをデフォルト値に設定して新しいインスタンスを作成するだけです。
This example defines a class called ShoppingListItem
, which encapsulates the name, quantity, and purchase state of an item in a shopping list:
この例では、ショッピング リスト内の商品の名前、数量、購入状態をカプセル化する、ShoppingListItem
というクラスを定義します。
class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
}
var item = ShoppingListItem()
Because all properties of the ShoppingListItem
class have default values, and because it’s a base class with no superclass, ShoppingListItem
automatically gains a default initializer implementation that creates a new instance with all of its properties set to their default values. (The name
property is an optional String
property, and so it automatically receives a default value of nil
, even though this value isn’t written in the code.) The example above uses the default initializer for the ShoppingListItem
class to create a new instance of the class with initializer syntax, written as ShoppingListItem()
, and assigns this new instance to a variable called item
.
ShoppingListItem
クラスのすべてのプロパティにはデフォルト値があり、スーパークラスのない基本クラスであるため、ShoppingListItem
は、すべてのプロパティがデフォルト値に設定された新しいインスタンスを作成するデフォルトのイニシャライザ実装を自動的に取得します。 (name
プロパティはオプションの String
プロパティであるため、この値がコードに記述されていない場合でも、自動的にデフォルト値 nil
を受け取ります。)上記の例では、ShoppingListItem
クラスのデフォルトの初期化子を使用して新しいインスタンスを作成しています。 ShoppingListItem()
として記述されたイニシャライザ構文を持つクラスのインスタンスを作成し、この新しいインスタンスを item
という変数に割り当てます。
Memberwise Initializers for Structure Types
構造体型のメンバーごとの初期化子
Structure types automatically receive a memberwise initializer if they don’t define any of their own custom initializers. Unlike a default initializer, the structure receives a memberwise initializer even if it has stored properties that don’t have default values.
構造型は、独自のカスタム初期化子を定義していない場合、メンバーごとの初期化子を自動的に受け取ります。 デフォルトのイニシャライザとは異なり、構造体は、デフォルト値を持たないプロパティが格納されている場合でも、メンバーごとのイニシャライザを受け取ります。
The memberwise initializer is a shorthand way to initialize the member properties of new structure instances. Initial values for the properties of the new instance can be passed to the memberwise initializer by name.
メンバーごとの初期化子は、新しい構造体インスタンスのメンバー プロパティを初期化する簡単な方法です。 新しいインスタンスのプロパティの初期値は、名前によってメンバーごとの初期化子に渡すことができます。
The example below defines a structure called Size
with two properties called width
and height
. Both properties are inferred to be of type Double
by assigning a default value of 0.0
.
以下の例では、width
とheight
という 2 つのプロパティを持つSize
という構造を定義しています。 両方のプロパティは、デフォルト値 0.0
を割り当てることで、Double
型であると推測されます。
The Size
structure automatically receives an init(width:height:)
memberwise initializer, which you can use to initialize a new Size
instance:
Size
構造体は、init(width:height:)
メンバーごとの初期化子を自動的に受け取ります。これを使用して、新しい Size
インスタンスを初期化できます。
struct Size {
var width = 0.0, height = 0.0
}
let twoByTwo = Size(width: 2.0, height: 2.0)
When you call a memberwise initializer, you can omit values for any properties that have default values. In the example above, the Size
structure has a default value for both its height
and width
properties. You can omit either property or both properties, and the initializer uses the default value for anything you omit. For example:
メンバーごとの初期化子を呼び出すときは、デフォルト値を持つプロパティの値を省略できます。 上の例では、Size
構造にはheight
とwidth
の両方のプロパティのデフォルト値があります。 いずれかのプロパティまたは両方のプロパティを省略でき、初期化子は省略したものに対してデフォルト値を使用します。 例えば:
let zeroByTwo = Size(height: 2.0)
print(zeroByTwo.width, zeroByTwo.height)
// Prints "0.0 2.0"
let zeroByZero = Size()
print(zeroByZero.width, zeroByZero.height)
// Prints "0.0 0.0"
Initializer Delegation for Value Types
値型のイニシャライザ委任
Initializers can call other initializers to perform part of an instance’s initialization. This process, known as initializer delegation, avoids duplicating code across multiple initializers.
イニシャライザは他のイニシャライザを呼び出して、インスタンスの初期化の一部を実行できます。 このプロセスはイニシャライザの委任として知られており、複数のイニシャライザ間でコードが重複することを回避します。
The rules for how initializer delegation works, and for what forms of delegation are allowed, are different for value types and class types. Value types (structures and enumerations) don’t support inheritance, and so their initializer delegation process is relatively simple, because they can only delegate to another initializer that they provide themselves. Classes, however, can inherit from other classes, as described in Inheritance. This means that classes have additional responsibilities for ensuring that all stored properties they inherit are assigned a suitable value during initialization. These responsibilities are described in Class Inheritance and Initialization below.
イニシャライザの委任がどのように機能するか、およびどのような形式の委任が許可されるかに関するルールは、値の型とクラスの型によって異なります。 値の型 (構造体と列挙型) は継承をサポートしていないため、そのイニシャライザの委任プロセスは、自身が提供する別のイニシャライザにのみ委任できるため、比較的単純です。 ただし、「継承」で説明されているように、クラスは他のクラスから継承できます。 これは、クラスが継承するすべての格納プロパティに初期化中に適切な値が割り当てられるようにする追加の責任があることを意味します。 これらの責任については、以下の「クラスの継承と初期化」で説明します。
For value types, you use self.init
to refer to other initializers from the same value type when writing your own custom initializers. You can call self.init
only from within an initializer.
値の型の場合、独自のカスタム イニシャライザを作成するときに、self.init
を使用して同じ値の型の他のイニシャライザを参照します。 self.init
はイニシャライザ内からのみ呼び出すことができます。
Note that if you define a custom initializer for a value type, you will no longer have access to the default initializer (or the memberwise initializer, if it’s a structure) for that type. This constraint prevents a situation in which additional essential setup provided in a more complex initializer is accidentally circumvented by someone using one of the automatic initializers.
値型のカスタム初期化子を定義すると、その型のデフォルトの初期化子 (構造体の場合はメンバーごとの初期化子) にアクセスできなくなることに注意してください。 この制約により、より複雑なイニシャライザで提供される追加の必須セットアップが、自動イニシャライザの 1 つを使用する人によって誤って回避されるという状況が防止されます。
Note
注釈
If you want your custom value type to be initializable with the default initializer and memberwise initializer, and also with your own custom initializers, write your custom initializers in an extension rather than as part of the value type’s original implementation. For more information, see Extensions.
カスタム値型をデフォルトのイニシャライザとメンバーごとのイニシャライザで初期化できるようにする場合、さらに独自のカスタム イニシャライザでも初期化できるようにする場合は、値型の元の実装の一部としてではなく、拡張機能にカスタム イニシャライザを記述します。 詳細については、「拡張機能」をご覧ください。
The following example defines a custom Rect
structure to represent a geometric rectangle. The example requires two supporting structures called Size
and Point
, both of which provide default values of 0.0
for all of their properties:
次の例では、幾何学的な長方形を表すカスタム Rect
構造を定義します。 この例では、「Size
」と「Point
」という 2 つのサポート構造が必要です。どちらも、すべてのプロパティにデフォルト値 0.0
を提供します。
struct Size {
var width = 0.0, height = 0.0
}
struct Point {
var x = 0.0, y = 0.0
}
You can initialize the Rect
structure below in one of three ways — by using its default zero-initialized origin
and size
property values, by providing a specific origin point and size, or by providing a specific center point and size. These initialization options are represented by three custom initializers that are part of the Rect
structure’s definition:
以下の Rect
構造は 3 つの方法のいずれかで初期化できます。デフォルトのゼロ初期化されたorigin
とsize
のプロパティ値を使用するか、特定の原点とサイズを指定するか、特定の中心点とサイズを指定します。 これらの初期化オプションは、Rect
構造の定義の一部である 3 つのカスタム初期化子によって表されます。
struct Rect {
var origin = Point()
var size = Size()
init() {}
init(origin: Point, size: Size) {
self.origin = origin
self.size = size
}
init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
The first Rect
initializer, init()
, is functionally the same as the default initializer that the structure would have received if it didn’t have its own custom initializers. This initializer has an empty body, represented by an empty pair of curly braces {}
. Calling this initializer returns a Rect
instance whose origin
and size
properties are both initialized with the default values of Point(x: 0.0, y: 0.0)
and Size(width: 0.0, height: 0.0)
from their property definitions:
最初の Rect
イニシャライザ init()
は、独自のカスタム イニシャライザがない場合に構造体が受け取るデフォルトのイニシャライザと機能的には同じです。 このイニシャライザには空の本体があり、空の中括弧 {}
で表されます。 このイニシャライザを呼び出すと、origin
プロパティと size
プロパティが両方ともプロパティ定義の Point(x: 0.0, y: 0.0)
と Size(width: 0.0, height: 0.0)
のデフォルト値で初期化された Rect
インスタンスが返されます。
let basicRect = Rect()
// basicRect's origin is (0.0, 0.0) and its size is (0.0, 0.0)
The second Rect
initializer, init(origin:size:)
, is functionally the same as the memberwise initializer that the structure would have received if it didn’t have its own custom initializers. This initializer simply assigns the origin
and size
argument values to the appropriate stored properties:
2 番目の Rect
イニシャライザ、init(origin:size:)
は、構造体が独自のカスタム イニシャライザを持たない場合に受け取るメンバーごとのイニシャライザと機能的には同じです。 このイニシャライザは、origin
と size
の引数の値を適切な格納プロパティに割り当てるだけです。
let originRect = Rect(origin: Point(x: 2.0, y: 2.0),
size: Size(width: 5.0, height: 5.0))
// originRect's origin is (2.0, 2.0) and its size is (5.0, 5.0)
The third Rect
initializer, init(center:size:)
, is slightly more complex. It starts by calculating an appropriate origin point based on a center
point and a size
value. It then calls (or delegates) to the init(origin:size:)
initializer, which stores the new origin and size values in the appropriate properties:
3 番目の Rect
イニシャライザー、init(center:size:)
は少し複雑です。 まず、center
点とsize
値に基づいて適切な原点を計算します。 次に、init(origin:size:)
イニシャライザを呼び出し(または委任)、新しい原点とサイズの値を適切なプロパティに保存します。
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),
size: Size(width: 3.0, height: 3.0))
// centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0)
The init(center:size:)
initializer could have assigned the new values of origin
and size
to the appropriate properties itself. However, it’s more convenient (and clearer in intent) for the init(center:size:)
initializer to take advantage of an existing initializer that already provides exactly that functionality.
init(center:size:)
イニシャライザは、origin
と size
の新しい値を適切なプロパティ自体に割り当てることができます。 ただし、init(center:size:)
イニシャライザでは、その機能をすでに提供している既存のイニシャライザを利用する方が便利です(そして意図が明確です)。
Note
注釈
For an alternative way to write this example without defining the init()
and init(origin:size:)
initializers yourself, see Extensions.
init()
および init(origin:size:)
イニシャライザを自分で定義せずにこの例を記述する別の方法については、「拡張機能」を参照してください。
Class Inheritance and Initialization
クラスの継承と初期化
All of a class’s stored properties — including any properties the class inherits from its superclass — must be assigned an initial value during initialization.
クラスに保存されているすべてのプロパティ(クラスがそのスーパークラスから継承するプロパティを含む)には、初期化中に初期値を割り当てる必要があります。
Swift defines two kinds of initializers for class types to help ensure all stored properties receive an initial value. These are known as designated initializers and convenience initializers.
Swift では、格納されているすべてのプロパティが初期値を確実に受け取ることができるように、クラス型に対して 2 種類のイニシャライザを定義しています。 これらは、指定イニシャライザおよび軽便イニシャライザとして知られています。
Designated Initializers and Convenience Initializers
指定イニシャライザと軽便イニシャライザ
Designated initializers are the primary initializers for a class. A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up the superclass chain.
指定イニシャライザは、クラスの主要な初期化子です。 指定イニシャライザは、そのクラスによって導入されたすべてのプロパティを完全に初期化し、適切なスーパークラス イニシャライザを呼び出して、スーパークラス チェーンまで初期化プロセスを続行します。
Classes tend to have very few designated initializers, and it’s quite common for a class to have only one. Designated initializers are “funnel” points through which initialization takes place, and through which the initialization process continues up the superclass chain.
クラスには指定イニシャライザがほとんどない傾向があり、クラスに 1 つしか初期化子がないこともよくあります。 指定イニシャライザは、初期化が行われ、初期化プロセスがスーパークラスへ連鎖を続ける「漏斗」ポイントです。
Every class must have at least one designated initializer. In some cases, this requirement is satisfied by inheriting one or more designated initializers from a superclass, as described in Automatic Initializer Inheritance below.
すべてのクラスには、少なくとも 1 つの指定イニシャライザが必要です。 場合によっては、この要件は、以下の「自動イニシャライザの継承」で説明するように、スーパークラスから 1 つ以上の指定イニシャライザを継承することによって満たされます。
Convenience initializers are secondary, supporting initializers for a class. You can define a convenience initializer to call a designated initializer from the same class as the convenience initializer with some of the designated initializer’s parameters set to default values. You can also define a convenience initializer to create an instance of that class for a specific use case or input value type.
軽便イニシャライザは二次的なもので、クラスのイニシャライザをサポートします。 指定イニシャライザのパラメータの一部をデフォルト値に設定して、軽便イニシャライザと同じクラスから指定イニシャライザを呼び出すように軽便イニシャライザを定義できます。 また、軽便イニシャライザを定義して、特定のユース ケースまたは入力値の型に対してそのクラスのインスタンスを作成することもできます。
You don’t have to provide convenience initializers if your class doesn’t require them. Create convenience initializers whenever a shortcut to a common initialization pattern will save time or make initialization of the class clearer in intent.
クラスが軽便イニシャライザを必要としない場合は、軽便イニシャライザを提供する必要はありません。 共通の初期化パターンへのショートカットにより時間を節約したり、クラスの初期化の意図を明確にしたりできる場合は常に、軽便イニシャライザを作成します。
Syntax for Designated and Convenience Initializers
指定イニシャライザと軽便イニシャライザの構文
Designated initializers for classes are written in the same way as simple initializers for value types:
クラスの指定イニシャライザは、値型の単純なイニシャライザと同じ方法で記述されます。
init(<#parameters#>) {
<#statements#>
}
Convenience initializers are written in the same style, but with the convenience
modifier placed before the init
keyword, separated by a space:
軽便イニシャライザは同じスタイルで記述されますが、convenience
修飾子は init
キーワードの前にスペースで区切って配置されます。
convenience init(<#parameters#>) {
<#statements#>
}
Initializer Delegation for Class Types
クラス型のイニシャライザ委任
To simplify the relationships between designated and convenience initializers, Swift applies the following three rules for delegation calls between initializers:Rule 1
指定イニシャライザと軽便イニシャライザの間の関係を単純化するために、Swift はイニシャライザ間の委任呼び出しに次の 3 つのルールを適用します。ルール 1
A designated initializer must call a designated initializer from its immediate superclass.Rule 2
指定イニシャライザは、その直接のスーパークラスから指定イニシャライザを呼び出す必要があります。ルール 2
A convenience initializer must call another initializer from the same class.Rule 3
軽便イニシャライザは、同じクラスの別のイニシャライザを呼び出す必要があります。ルール 3
A convenience initializer must ultimately call a designated initializer.
軽便イニシャライザは、最終的に指定イニシャライザを呼び出す必要があります。
A simple way to remember this is:
これを覚える簡単な方法は次のとおりです。
- Designated initializers must always delegate up.
- 指定イニシャライザは常に上位委任する必要があります。
- Convenience initializers must always delegate across.
- 軽便イニシャライザは常に横断委任する必要があります。
These rules are illustrated in the figure below:
これらのルールを次の図に示します。
Here, the superclass has a single designated initializer and two convenience initializers. One convenience initializer calls another convenience initializer, which in turn calls the single designated initializer. This satisfies rules 2 and 3 from above. The superclass doesn’t itself have a further superclass, and so rule 1 doesn’t apply.
ここで、スーパークラスには 1 つの指定イニシャライザと 2 つの軽便イニシャライザがあります。 1 つの軽便イニシャライザが別の軽便イニシャライザを呼び出し、次にその軽便イニシャライザが 1 つの指定イニシャライザを呼び出します。 これは、上記のルール 2 と 3 を満たします。 スーパークラス自体にはさらにスーパークラスがないため、ルール 1 は適用されません。
The subclass in this figure has two designated initializers and one convenience initializer. The convenience initializer must call one of the two designated initializers, because it can only call another initializer from the same class. This satisfies rules 2 and 3 from above. Both designated initializers must call the single designated initializer from the superclass, to satisfy rule 1 from above.
この図のサブクラスには、2 つの指定イニシャライザと 1 つの軽便イニシャライザがあります。 軽便イニシャライザは、同じクラスの別のイニシャライザのみを呼び出すことができるため、2 つの指定イニシャライザのうちの 1 つを呼び出す必要があります。 これは、上記のルール 2 と 3 を満たします。 両方の指定イニシャライザは、上記のルール 1 を満たすために、スーパークラスから 1 つの指定イニシャライザを呼び出す必要があります。
Note
注釈
These rules don’t affect how users of your classes create instances of each class. Any initializer in the diagram above can be used to create a fully initialized instance of the class they belong to. The rules only affect how you write the implementation of the class’s initializers.
これらのルールは、クラスのユーザーが各クラスのインスタンスを作成する方法には影響しません。 上の図の任意のイニシャライザを使用して、それらが属するクラスの完全に初期化されたインスタンスを作成できます。 ルールは、クラスのイニシャライザの実装の記述方法にのみ影響します。
The figure below shows a more complex class hierarchy for four classes. It illustrates how the designated initializers in this hierarchy act as “funnel” points for class initialization, simplifying the interrelationships among classes in the chain:
以下の図は、4 つのクラスのより複雑なクラス階層を示しています。 これは、この階層内の指定イニシャライザがクラス初期化の「漏斗」ポイントとしてどのように機能し、チェーン内のクラス間の相互関係を簡素化するかを示しています。
Two-Phase Initialization
2 段階の初期化
Class initialization in Swift is a two-phase process. In the first phase, each stored property is assigned an initial value by the class that introduced it. Once the initial state for every stored property has been determined, the second phase begins, and each class is given the opportunity to customize its stored properties further before the new instance is considered ready for use.
Swift のクラスの初期化は 2 段階のプロセスです。 最初のフェーズでは、格納された各プロパティに、それを導入したクラスによって初期値が割り当てられます。 すべての格納プロパティの初期状態が決定されると、第 2 フェーズが開始され、新しいインスタンスが使用可能とみなされる前に、各クラスに格納プロパティをさらにカスタマイズする機会が与えられます。
The use of a two-phase initialization process makes initialization safe, while still giving complete flexibility to each class in a class hierarchy. Two-phase initialization prevents property values from being accessed before they’re initialized, and prevents property values from being set to a different value by another initializer unexpectedly.
2 フェーズの初期化プロセスを使用すると、初期化が安全になると同時に、クラス階層内の各クラスに完全な柔軟性が与えられます。 2 フェーズ初期化では、プロパティ値が初期化される前にアクセスされることを防ぎ、別の初期化子によってプロパティ値が予期せず異なる値に設定されることを防ぎます。
Note
注釈
Swift’s two-phase initialization process is similar to initialization in Objective-C. The main difference is that during phase 1, Objective-C assigns zero or null values (such as 0
or nil
) to every property. Swift’s initialization flow is more flexible in that it lets you set custom initial values, and can cope with types for which 0
or nil
isn’t a valid default value.
Swift の 2 フェーズの初期化プロセスは、Objective-C の初期化に似ています。 主な違いは、フェーズ 1 で、Objective-C がすべてのプロパティにゼロまたは null 値(0
または nil
など)を割り当てることです。 Swift の初期化フローは、カスタム初期値を設定できるという点でより柔軟であり、0
または nil
が有効なデフォルト値ではない型にも対応できます。
Swift’s compiler performs four helpful safety-checks to make sure that two-phase initialization is completed without error:Safety check 1
Swift のコンパイラーは、2 フェーズの初期化がエラーなしで完了することを確認するために 4 つの有用な安全性チェックを実行します: 安全性チェック 1
A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.
指定イニシャライザは、スーパークラスイニシャライザに委任する前に、そのクラスによって導入されたすべてのプロパティが初期化されていることを確認する必要があります。
As mentioned above, the memory for an object is only considered fully initialized once the initial state of all of its stored properties is known. In order for this rule to be satisfied, a designated initializer must make sure that all of its own properties are initialized before it hands off up the chain.Safety check 2
上で述べたように、オブジェクトのメモリは、格納されているすべてのプロパティの初期状態が判明した場合にのみ、完全に初期化されたとみなされます。 このルールを満たすためには、指定イニシャライザは、チェーンを渡す前に、それ自体のプロパティがすべて初期化されていることを確認する必要があります。安全性チェック 2
A designated initializer must delegate up to a superclass initializer before assigning a value to an inherited property. If it doesn’t, the new value the designated initializer assigns will be overwritten by the superclass as part of its own initialization.Safety check 3
指定イニシャライザは、継承されたプロパティに値を割り当てる前に、スーパークラスイニシャライザに委任する必要があります。 そうでない場合、指定イニシャライザが割り当てる新しい値は、スーパークラス自体の初期化の一部としてスーパークラスによって上書きされます。安全性チェック 3
A convenience initializer must delegate to another initializer before assigning a value to any property (including properties defined by the same class). If it doesn’t, the new value the convenience initializer assigns will be overwritten by its own class’s designated initializer.Safety check 4
軽便イニシャライザは、プロパティ(同じクラスで定義されたプロパティを含む)に値を割り当てる前に、別のイニシャライザに委任する必要があります。 そうでない場合、軽便イニシャライザが割り当てる新しい値は、そのクラスの指定イニシャライザによって上書きされます。安全性チェック 4
An initializer can’t call any instance methods, read the values of any instance properties, or refer to self
as a value until after the first phase of initialization is complete.
イニシャライザの最初のフェーズが完了するまで、イニシャライザはインスタンス メソッドを呼び出したり、インスタンス プロパティの値を読み取ったり、値として self
を参照したりすることはできません。
The class instance isn’t fully valid until the first phase ends. Properties can only be accessed, and methods can only be called, once the class instance is known to be valid at the end of the first phase.
クラス インスタンスは、最初のフェーズが終了するまで完全には有効になりません。 最初のフェーズの終了時にクラス インスタンスが有効であることが判明した場合のみ、プロパティにアクセスでき、メソッドを呼び出すことができます。
Here’s how two-phase initialization plays out, based on the four safety checks above:
上記の 4 つの安全性チェックに基づいて、2 段階の初期化がどのように実行されるかを次に示します。
Phase 1
フェーズ 1
- A designated or convenience initializer is called on a class.
- 指定イニシャライザまたは軽便イニシャライザがクラスで呼び出されます。
- Memory for a new instance of that class is allocated. The memory isn’t yet initialized.
- そのクラスの新しいインスタンス用のメモリが割り当てられます。 メモリはまだ初期化されていません。
- A designated initializer for that class confirms that all stored properties introduced by that class have a value. The memory for these stored properties is now initialized.
- そのクラスに指定イニシャライザは、そのクラスによって導入されたすべての格納されたプロパティに値があることを確認します。 これらの保存されたプロパティのメモリが初期化されます。
- The designated initializer hands off to a superclass initializer to perform the same task for its own stored properties.
- 指定イニシャライザは、スーパークラス イニシャライザに引き渡して、自身の格納されたプロパティに対して同じタスクを実行します。
- This continues up the class inheritance chain until the top of the chain is reached.
- これは、チェーンの先頭に到達するまでクラス継承チェーンを上っていきます。
- Once the top of the chain is reached, and the final class in the chain has ensured that all of its stored properties have a value, the instance’s memory is considered to be fully initialized, and phase 1 is complete.
- チェーンの先頭に到達し、チェーンの最後のクラスが、格納されているすべてのプロパティに値があることを確認すると、インスタンスのメモリは完全に初期化されたとみなされ、フェーズ 1 が完了します。
Phase 2
フェーズ2
- Working back down from the top of the chain, each designated initializer in the chain has the option to customize the instance further. Initializers are now able to access
self
and can modify its properties, call its instance methods, and so on. - チェーンの先頭から遡って、チェーン内の各指定イニシャライザには、インスタンスをさらにカスタマイズするオプションがあります。 イニシャライザは
self
にアクセスできるようになり、そのプロパティを変更したり、そのインスタンス メソッドを呼び出したりできるようになります。 - Finally, any convenience initializers in the chain have the option to customize the instance and to work with
self
. - 最後に、チェーン内の軽便イニシャライザには、インスタンスをカスタマイズして
self
を操作するオプションがあります。
Here’s how phase 1 looks for an initialization call for a hypothetical subclass and superclass:
フェーズ 1 で、仮想のサブクラスとスーパークラスの初期化呼び出しを探す方法を次に示します。
In this example, initialization begins with a call to a convenience initializer on the subclass. This convenience initializer can’t yet modify any properties. It delegates across to a designated initializer from the same class.
この例では、初期化はサブクラスの軽便イニシャライザの呼び出しから始まります。 この軽便イニシャライザはまだプロパティを変更できません。 同じクラスの指定イニシャライザに委譲します。
The designated initializer makes sure that all of the subclass’s properties have a value, as per safety check 1. It then calls a designated initializer on its superclass to continue the initialization up the chain.
指定イニシャライザは、安全性チェック 1 に従って、すべてのサブクラスのプロパティに値があることを確認します。次に、そのスーパークラスで指定イニシャライザを呼び出して、チェーンの上の初期化を続行します。
The superclass’s designated initializer makes sure that all of the superclass properties have a value. There are no further superclasses to initialize, and so no further delegation is needed.
スーパークラスの指定イニシャライザにより、すべてのスーパークラス プロパティに値が設定されるようになります。 これ以上初期化するスーパークラスはないため、それ以上の委任は必要ありません。
As soon as all properties of the superclass have an initial value, its memory is considered fully initialized, and phase 1 is complete.
スーパークラスのすべてのプロパティが初期値を持つとすぐに、そのメモリは完全に初期化されたとみなされ、フェーズ 1 が完了します。
Here’s how phase 2 looks for the same initialization call:
フェーズ 2 で同じ初期化呼び出しを探す方法は次のとおりです。
The superclass’s designated initializer now has an opportunity to customize the instance further (although it doesn’t have to).
スーパークラスの指定イニシャライザは、インスタンスをさらにカスタマイズできるようになりました (ただし、そうする必要はありません)。
Once the superclass’s designated initializer is finished, the subclass’s designated initializer can perform additional customization (although again, it doesn’t have to).
スーパークラスの指定イニシャライザが完了すると、サブクラスの指定イニシャライザは追加のカスタマイズを実行できます (繰り返しになりますが、そうする必要はありません)。
Finally, once the subclass’s designated initializer is finished, the convenience initializer that was originally called can perform additional customization.
最後に、サブクラスの指定イニシャライザが完了すると、最初に呼び出された軽便イニシャライザは追加のカスタマイズを実行できます。
Initializer Inheritance and Overriding
イニシャライザの継承とオーバーライド
Unlike subclasses in Objective-C, Swift subclasses don’t inherit their superclass initializers by default. Swift’s approach prevents a situation in which a simple initializer from a superclass is inherited by a more specialized subclass and is used to create a new instance of the subclass that isn’t fully or correctly initialized.
Objective-C のサブクラスとは異なり、Swift サブクラスはデフォルトではスーパークラスイニシャライザを継承しません。 Swift のアプローチは、スーパークラスの単純なイニシャライザがより特化されたサブクラスに継承され、完全にまたは正しく初期化されていないサブクラスの新しいインスタンスを作成するために使用されるという状況を防ぎます。
Note
注釈
Superclass initializers are inherited in certain circumstances, but only when it’s safe and appropriate to do so. For more information, see Automatic Initializer Inheritance below.
スーパークラスのイニシャライザは特定の状況で継承されますが、それが安全で適切な場合に限ります。 詳細については、以下の「自動イニシャライザの継承」を参照してください。
If you want a custom subclass to present one or more of the same initializers as its superclass, you can provide a custom implementation of those initializers within the subclass.
カスタム サブクラスでそのスーパークラスと同じイニシャライザを 1 つ以上提示したい場合は、サブクラス内でそれらのイニシャライザのカスタム実装を提供できます。
When you write a subclass initializer that matches a superclass designated initializer, you are effectively providing an override of that designated initializer. Therefore, you must write the override
modifier before the subclass’s initializer definition. This is true even if you are overriding an automatically provided default initializer, as described in Default Initializers.
スーパークラスの指定イニシャライザと一致するサブクラスのイニシャライザを作成すると、事実上、その指定イニシャライザのオーバーライドを提供することになります。 したがって、サブクラスのイニシャライザ定義の前に override
修飾子を記述する必要があります。 これは、「デフォルトのイニシャライザ」で説明されているように、自動的に提供されるデフォルトのイニシャライザをオーバーライドする場合にも当てはまります。
As with an overridden property, method or subscript, the presence of the override
modifier prompts Swift to check that the superclass has a matching designated initializer to be overridden, and validates that the parameters for your overriding initializer have been specified as intended.
オーバーライドされたプロパティ、メソッド、またはサブスクリプトと同様に、override
修飾子の存在により、Swift はスーパークラスにオーバーライドされる一致する指定イニシャライザがあることを確認し、オーバーライドするイニシャライザのパラメータが意図したとおりに指定されていることを検証します。
Note
注釈
You always write the override
modifier when overriding a superclass designated initializer, even if your subclass’s implementation of the initializer is a convenience initializer.
スーパークラスで指定イニシャライザをオーバーライドするときは、サブクラスのイニシャライザ実装が軽便イニシャライザである場合でも、常に override
修飾子を記述します。
Conversely, if you write a subclass initializer that matches a superclass convenience initializer, that superclass convenience initializer can never be called directly by your subclass, as per the rules described above in Initializer Delegation for Class Types. Therefore, your subclass is not (strictly speaking) providing an override of the superclass initializer. As a result, you don’t write the override
modifier when providing a matching implementation of a superclass convenience initializer.
逆に、スーパークラスの軽便イニシャライザと一致するサブクラス イニシャライザを作成した場合、上記の「クラス 型のイニシャライザ委任」で説明されているルールに従って、そのスーパークラスの軽便イニシャライザをサブクラスから直接呼び出すことはできません。 したがって、サブクラスは (厳密に言えば) スーパークラスイニシャライザのオーバーライドを提供しません。 その結果、スーパークラスの軽便イニシャライザの対応する実装を提供するときに、override
修飾子を記述する必要はありません。
The example below defines a base class called Vehicle
. This base class declares a stored property called numberOfWheels
, with a default Int
value of 0
. The numberOfWheels
property is used by a computed property called description
to create a String
description of the vehicle’s characteristics:
以下の例では、Vehicle
という基本クラスを定義しています。 この基本クラスは、numberOfWheels
という保存されたプロパティを宣言し、デフォルトの Int
値は 0
です。numberOfWheels
プロパティは、車両の特性のString
説明を作成するために、description
と呼ばれる計算されたプロパティによって使用されます。
class Vehicle {
var numberOfWheels = 0
var description: String {
return "\(numberOfWheels) wheel(s)"
}
}
The Vehicle
class provides a default value for its only stored property, and doesn’t provide any custom initializers itself. As a result, it automatically receives a default initializer, as described in Default Initializers. The default initializer (when available) is always a designated initializer for a class, and can be used to create a new Vehicle
instance with a numberOfWheels
of 0
:
Vehicle
クラスは、保存される唯一のプロパティのデフォルト値を提供し、カスタム初期化子自体は提供しません。 その結果、「デフォルトのイニシャライザ」で説明されているように、デフォルトのイニシャライザが自動的に受信されます。 デフォルトのイニシャライザ(利用可能な場合)は常にクラスに指定イニシャライザであり、numberOfWheels
が 0
の新しい Vehicle
インスタンスを作成するために使用できます。
let vehicle = Vehicle()
print("Vehicle: \(vehicle.description)")
// Vehicle: 0 wheel(s)
The next example defines a subclass of Vehicle
called Bicycle
:
次の例では、Bicycle
という Vehicle
のサブクラスを定義します。
class Bicycle: Vehicle {
override init() {
super.init()
numberOfWheels = 2
}
}
The Bicycle
subclass defines a custom designated initializer, init()
. This designated initializer matches a designated initializer from the superclass of Bicycle
, and so the Bicycle
version of this initializer is marked with the override
modifier.
Bicycle
サブクラスは、カスタム指定イニシャライザ init()
を定義します。 この指定イニシャライザは、Bicycle
のスーパークラスの指定イニシャライザと一致するため、このイニシャライザの Bicycle
バージョンは override
修飾子でマークされます。
The init()
initializer for Bicycle
starts by calling super.init()
, which calls the default initializer for the Bicycle
class’s superclass, Vehicle
. This ensures that the numberOfWheels
inherited property is initialized by Vehicle
before Bicycle
has the opportunity to modify the property. After calling super.init()
, the original value of numberOfWheels
is replaced with a new value of 2
.
Bicycle
の init()
イニシャライザは、super.init()
を呼び出すことで開始されます。これにより、Bicycle
クラスのスーパークラスである Vehicle
のデフォルトのイニシャライザが呼び出されます。 これにより、Bicycle
がプロパティを変更する機会を持つ前に、継承されたnumberOfWheels
プロパティが Vehicle
によって初期化されるようになります。 super.init()
を呼び出した後、numberOfWheels
の元の値は新しい値 2
に置き換えられます。
If you create an instance of Bicycle
, you can call its inherited description
computed property to see how its numberOfWheels
property has been updated:
Bicycle
のインスタンスを作成する場合は、その継承されたdescription
の計算プロパティを呼び出して、numberOfWheels
プロパティがどのように更新されたかを確認できます。
let bicycle = Bicycle()
print("Bicycle: \(bicycle.description)")
// Bicycle: 2 wheel(s)
If a subclass initializer performs no customization in phase 2 of the initialization process, and the superclass has a synchronous, zero-argument designated initializer, you can omit a call to super.init()
after assigning values to all of the subclass’s stored properties. If the superclass’s initializer is asynchronous, you need to write await super.init()
explicitly.
サブクラス初期化子が初期化プロセスのフェーズ 2 でカスタマイズを実行せず、スーパークラスに同期の引数ゼロの指定イニシャライザがある場合は、サブクラスのすべての格納プロパティに値を割り当てた後、super.init()
への呼び出しを省略できます。 スーパークラスのイニシャライザが非同期の場合は、await super.init()
を明示的に記述する必要があります。
This example defines another subclass of Vehicle
, called Hoverboard
. In its initializer, the Hoverboard
class sets only its color
property. Instead of making an explicit call to super.init()
, this initializer relies on an implicit call to its superclass’s initializer to complete the process.
この例では、Hoverboard
と呼ばれる、Vehicle
の別のサブクラスを定義します。 Hoverboard
クラスは、初期化子で color
プロパティのみを設定します。 super.init()
を明示的に呼び出す代わりに、このイニシャライザはスーパークラスのイニシャライザへの暗黙的な呼び出しに依存してプロセスを完了します。
class Hoverboard: Vehicle {
var color: String
init(color: String) {
self.color = color
// super.init() implicitly called here
}
override var description: String {
return "\(super.description) in a beautiful \(color)"
}
}
An instance of Hoverboard
uses the default number of wheels supplied by the Vehicle
initializer.
Hoverboard
のインスタンスは、Vehicle
イニシャライザによって提供されるデフォルトのホイール数を使用します。
let hoverboard = Hoverboard(color: "silver")
print("Hoverboard: \(hoverboard.description)")
// Hoverboard: 0 wheel(s) in a beautiful silver
Note
注釈
Subclasses can modify inherited variable properties during initialization, but can’t modify inherited constant properties.
サブクラスは、初期化中に継承された変数プロパティを変更できますが、継承された定数プロパティを変更することはできません。
Automatic Initializer Inheritance
自動イニシャライザの継承
As mentioned above, subclasses don’t inherit their superclass initializers by default. However, superclass initializers are automatically inherited if certain conditions are met. In practice, this means that you don’t need to write initializer overrides in many common scenarios, and can inherit your superclass initializers with minimal effort whenever it’s safe to do so.
上で述べたように、サブクラスはデフォルトではスーパークラス初期化子を継承しません。 ただし、特定の条件が満たされた場合、スーパークラス初期化子は自動的に継承されます。 実際には、これは、多くの一般的なシナリオでイニシャライザのオーバーライドを記述する必要がなく、安全な場合はいつでも最小限の労力でスーパークラスのイニシャライザを継承できることを意味します。
Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply:Rule 1
サブクラスに導入する新しいプロパティにデフォルト値を指定すると、次の 2 つのルールが適用されます。ルール 1
If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.Rule 2
サブクラスが指定イニシャライザを定義していない場合、サブクラスはそのスーパークラスの指定イニシャライザをすべて自動的に継承します。ルール 2
If your subclass provides an implementation of all of its superclass designated initializers — either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition — then it automatically inherits all of the superclass convenience initializers.
サブクラスが、ルール 1 に従って継承するか、定義の一部としてカスタム実装を提供することによって、スーパークラスですべての指定イニシャライザの実装を提供する場合、スーパークラスの軽便イニシャライザはすべて自動的に継承されます。
These rules apply even if your subclass adds further convenience initializers.
これらのルールは、サブクラスがさらに軽便イニシャライザを追加する場合にも適用されます。
Note
注釈
A subclass can implement a superclass designated initializer as a subclass convenience initializer as part of satisfying rule 2.
サブクラスは、ルール 2 を満たす一環として、スーパークラス指定のイニシャライザをサブクラス軽便イニシャライザとして実装できます。
Designated and Convenience Initializers in Action
動作中の指定と軽便イニシャライザ
The following example shows designated initializers, convenience initializers, and automatic initializer inheritance in action. This example defines a hierarchy of three classes called Food
, RecipeIngredient
, and ShoppingListItem
, and demonstrates how their initializers interact.
次の例は、指定イニシャライザ、軽便イニシャライザ、および自動イニシャライザ継承の動作を示しています。 この例では、Food
、RecipeIngredient
、ShoppingListItem
という 3 つのクラスの階層を定義し、それらの初期化子がどのように相互作用するかを示します。
The base class in the hierarchy is called Food
, which is a simple class to encapsulate the name of a foodstuff. The Food
class introduces a single String
property called name
and provides two initializers for creating Food
instances:
階層内の基本クラスは Food
と呼ばれ、食品の名前をカプセル化する単純なクラスです。 Food
クラスは、name
と呼ばれる単一の String
プロパティを導入し、Food
インスタンスを作成するための 2 つの初期化子を提供します。
class Food {
var name: String
init(name: String) {
self.name = name
}
convenience init() {
self.init(name: "[Unnamed]")
}
}
The figure below shows the initializer chain for the Food
class:
以下の図は、Food クラスの初期化連鎖を示しています。
Classes don’t have a default memberwise initializer, and so the Food
class provides a designated initializer that takes a single argument called name
. This initializer can be used to create a new Food
instance with a specific name:
クラスにはデフォルトのメンバーごとのイニシャライザがないため、Food
クラスは、name
という単一の引数を取る指定イニシャライザを提供します。 このイニシャライザを使用して、特定の名前を持つ新しい Food
インスタンスを作成できます。
let namedMeat = Food(name: "Bacon")
// namedMeat's name is "Bacon"
The init(name: String)
initializer from the Food
class is provided as a designated initializer, because it ensures that all stored properties of a new Food
instance are fully initialized. The Food
class doesn’t have a superclass, and so the init(name: String)
initializer doesn’t need to call super.init()
to complete its initialization.
Food
クラスの init(name: String)
イニシャライザは、新しい Food
インスタンスのすべての保存プロパティが完全に初期化されることを保証するため、指定されたイニシャライザとして提供されます。 Food
クラスにはスーパークラスがないため、init(name: String)
イニシャライザは初期化を完了するために super.init()
を呼び出す必要はありません。
The Food
class also provides a convenience initializer, init()
, with no arguments. The init()
initializer provides a default placeholder name for a new food by delegating across to the Food
class’s init(name: String)
with a name
value of [Unnamed]
:
Food
クラスは、引数なしの軽便イニシャライザ init()
も提供します。 init()
イニシャライザは、name
の値が [Unnamed]
である Food
クラスの init(name: String)
に委任することで、新しい食品のデフォルトのプレースホルダ名を提供します。
let mysteryMeat = Food()
// mysteryMeat's name is "[Unnamed]"
The second class in the hierarchy is a subclass of Food
called RecipeIngredient
. The RecipeIngredient
class models an ingredient in a cooking recipe. It introduces an Int
property called quantity
(in addition to the name
property it inherits from Food
) and defines two initializers for creating RecipeIngredient
instances:
階層の 2 番目のクラスは、RecipeIngredient
と呼ばれる Food
のサブクラスです。 RecipeIngredient
クラスは、料理レシピの材料をモデル化します。 これは、(Food
から継承する name
プロパティに加えて)quantity
と呼ばれる Int
プロパティを導入し、RecipeIngredient
インスタンスを作成するための 2 つの初期化子を定義します。
class RecipeIngredient: Food {
var quantity: Int
init(name: String, quantity: Int) {
self.quantity = quantity
super.init(name: name)
}
override convenience init(name: String) {
self.init(name: name, quantity: 1)
}
}
The figure below shows the initializer chain for the RecipeIngredient
class:
以下の図は、RecipeIngredient
クラスの初期化チェーンを示しています。
The RecipeIngredient
class has a single designated initializer, init(name: String, quantity: Int)
, which can be used to populate all of the properties of a new RecipeIngredient
instance. This initializer starts by assigning the passed quantity
argument to the quantity
property, which is the only new property introduced by RecipeIngredient
. After doing so, the initializer delegates up to the init(name: String)
initializer of the Food
class. This process satisfies safety check 1 from Two-Phase Initialization above.
RecipeIngredient
クラスには、単一の指定イニシャライザ init(name: String, quantity: Int)
があり、これを使用して新しい RecipeIngredient
インスタンスのすべてのプロパティを設定できます。 このイニシャライザは、渡されたquantity
引数をquantity
プロパティに割り当てることから始まります。これは、RecipeIngredient
によって導入された唯一の新しいプロパティです。 そうすることで、イニシャライザは Food
クラスの init(name: String)
イニシャライザまで委譲します。 このプロセスは、上記の 2 フェーズ初期化の安全性チェック 1 を満たします。
RecipeIngredient
also defines a convenience initializer, init(name: String)
, which is used to create a RecipeIngredient
instance by name alone. This convenience initializer assumes a quantity of 1
for any RecipeIngredient
instance that’s created without an explicit quantity. The definition of this convenience initializer makes RecipeIngredient
instances quicker and more convenient to create, and avoids code duplication when creating several single-quantity RecipeIngredient
instances. This convenience initializer simply delegates across to the class’s designated initializer, passing in a quantity
value of 1
.
RecipeIngredient
は、名前だけで RecipeIngredient
インスタンスを作成するために使用される軽便イニシャライザ init(name: String)
も定義します。 この軽便イニシャライザは、明示的な数量を指定せずに作成された RecipeIngredient
インスタンスの数量が 1
であると想定します。 この軽便イニシャライザの定義により、RecipeIngredient
インスタンスの作成がより迅速かつ便利になり、複数の単一数量の RecipeIngredient
インスタンスを作成する際のコードの重複が回避されます。 この軽便イニシャライザは、単にクラスの指定イニシャライザに委任し、数量値 1 を渡します。
The init(name: String)
convenience initializer provided by RecipeIngredient
takes the same parameters as the init(name: String)
designated initializer from Food
. Because this convenience initializer overrides a designated initializer from its superclass, it must be marked with the override
modifier (as described in Initializer Inheritance and Overriding).
RecipeIngredient
によって提供される init(name: String)
軽便イニシャライザは、Food
の init(name: String)
指定イニシャライザと同じパラメータを受け取ります。 この軽便イニシャライザは、指定イニシャライザをそのスーパークラスからオーバーライドするため、オーバーライド修飾子でマークする必要があります(イニシャライザの継承とオーバーライドで説明されています)。
Even though RecipeIngredient
provides the init(name: String)
initializer as a convenience initializer, RecipeIngredient
has nonetheless provided an implementation of all of its superclass’s designated initializers. Therefore, RecipeIngredient
automatically inherits all of its superclass’s convenience initializers too.
RecipeIngredient
は軽便イニシャライザとして init(name: String)
イニシャライザを提供しますが、それでも、RecipeIngredient
はそのスーパークラスの指定されたイニシャライザすべての実装を提供しています。 したがって、RecipeIngredient
は、そのスーパークラスの軽便イニシャライザもすべて自動的に継承します。
In this example, the superclass for RecipeIngredient
is Food
, which has a single convenience initializer called init()
. This initializer is therefore inherited by RecipeIngredient
. The inherited version of init()
functions in exactly the same way as the Food
version, except that it delegates to the RecipeIngredient
version of init(name: String)
rather than the Food
version.
この例では、RecipeIngredient
のスーパークラスは Food
で、これには init()
という単一の軽便イニシャライザがあります。 したがって、このイニシャライザは、RecipeIngredient
によって継承されます。 継承されたバージョンの init()
は、Food
バージョンではなく、RecipeIngredient
バージョンの init(name: String)
に委任されることを除いて、Food
バージョンとまったく同じように機能します。
All three of these initializers can be used to create new RecipeIngredient
instances:
これら 3 つのイニシャライザはすべて、新しい RecipeIngredient インスタンスの作成に使用できます。
let oneMysteryItem = RecipeIngredient()
let oneBacon = RecipeIngredient(name: "Bacon")
let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6)
The third and final class in the hierarchy is a subclass of RecipeIngredient
called ShoppingListItem
. The ShoppingListItem
class models a recipe ingredient as it appears in a shopping list.
階層内の 3 番目で最後のクラスは、ShoppingListItem
と呼ばれる RecipeIngredient
のサブクラスです。 ShoppingListItem
クラスは、ショッピング リストに表示されるレシピの材料をモデル化します。
Every item in the shopping list starts out as “unpurchased”. To represent this fact, ShoppingListItem
introduces a Boolean property called purchased
, with a default value of false
. ShoppingListItem
also adds a computed description
property, which provides a textual description of a ShoppingListItem
instance:
買い物リスト内のすべての商品は「未購入」として開始されます。 この事実を表すために、ShoppingListItem
は、デフォルト値が false
の、purchased
と呼ばれるブール型プロパティを導入します。 ShoppingListItem
は、ShoppingListItem
インスタンスのテキストによる説明を提供する計算されたdescription
プロパティも追加します。
class ShoppingListItem: RecipeIngredient {
var purchased = false
var description: String {
var output = "\(quantity) x \(name)"
output += purchased ? " ✔" : " ✘"
return output
}
}
Note
注釈
ShoppingListItem
doesn’t define an initializer to provide an initial value for purchased
, because items in a shopping list (as modeled here) always start out unpurchased.
ShoppingListItem
では、purchased
の初期値を提供するイニシャライザは定義されていません。これは、ショッピング リスト内の商品(ここでモデル化されている)は常に未購入の状態から始まるためです。
Because it provides a default value for all of the properties it introduces and doesn’t define any initializers itself, ShoppingListItem
automatically inherits all of the designated and convenience initializers from its superclass.
ShoppingListItem
は、導入されるすべてのプロパティにデフォルト値を提供し、それ自体は初期化子を定義しないため、すべての指定と軽便イニシャライザをそのスーパークラスから自動的に継承します。
The figure below shows the overall initializer chain for all three classes:
以下の図は、3 つのクラスすべての全体的なイニシャライザ連鎖を示しています。
You can use all three of the inherited initializers to create a new ShoppingListItem
instance:
継承された 3 つのイニシャライザをすべて使用して、新しい ShoppingListItem
インスタンスを作成できます。
var breakfastList = [
ShoppingListItem(),
ShoppingListItem(name: "Bacon"),
ShoppingListItem(name: "Eggs", quantity: 6),
]
breakfastList[0].name = "Orange juice"
breakfastList[0].purchased = true
for item in breakfastList {
print(item.description)
}
// 1 x Orange juice ✔
// 1 x Bacon ✘
// 6 x Eggs ✘
Here, a new array called breakfastList
is created from an array literal containing three new ShoppingListItem
instances. The type of the array is inferred to be [ShoppingListItem]
. After the array is created, the name of the ShoppingListItem
at the start of the array is changed from "[Unnamed]"
to "Orange juice"
and it’s marked as having been purchased. Printing the description of each item in the array shows that their default states have been set as expected.
ここでは、3 つの新しい ShoppingListItem
インスタンスを含む配列リテラルから、breakfastList
という新しい配列が作成されます。 配列の型は [ShoppingListItem]
であると推測されます。 配列が作成されると、配列の先頭にある ShoppingListItem
の名前が「[Unnamed]
」から「Orange juice
」に変更され、購入済みとしてマークされます。 配列内の各項目の説明を出力すると、それらのデフォルト状態が期待どおりに設定されていることがわかります。
Failable Initializers
失敗可能なイニシャライザ
It’s sometimes useful to define a class, structure, or enumeration for which initialization can fail. This failure might be triggered by invalid initialization parameter values, the absence of a required external resource, or some other condition that prevents initialization from succeeding.
初期化が失敗する可能性があるクラス、構造体、または列挙型を定義すると便利な場合があります。 この失敗は、無効な初期化パラメータ値、必要な外部リソースの欠如、または初期化の成功を妨げるその他の条件によって引き起こされる可能性があります。
To cope with initialization conditions that can fail, define one or more failable initializers as part of a class, structure, or enumeration definition. You write a failable initializer by placing a question mark after the init
keyword (init?
).
失敗する可能性のある初期化条件に対処するには、クラス、構造体、または列挙定義の一部として 1 つ以上の失敗可能な初期化子を定義します。 失敗可能なイニシャライザを作成するには、init
キーワード (init?
) の後に疑問符を置きます。
Note
注釈
You can’t define a failable and a nonfailable initializer with the same parameter types and names.
同じパラメーターの型と名前を使用して、失敗可能なイニシャライザーと失敗しないイニシャライザーを定義することはできません。
A failable initializer creates an optional value of the type it initializes. You write return nil
within a failable initializer to indicate a point at which initialization failure can be triggered.
失敗可能なイニシャライザは、初期化する型のオプションの値を作成します。 初期化の失敗がトリガーされる可能性があるポイントを示すには、失敗可能なイニシャライザ内に return nil
を記述します。
Note
注釈
Strictly speaking, initializers don’t return a value. Rather, their role is to ensure that self
is fully and correctly initialized by the time that initialization ends. Although you write return nil
to trigger an initialization failure, you don’t use the return
keyword to indicate initialization success.
厳密に言えば、イニシャライザは値を返しません。 むしろ、それらの役割は、初期化が終了するまでに self
が完全かつ正しく初期化されていることを確認することです。 初期化の失敗をトリガーするには return nil
を記述しますが、初期化の成功を示すために return
キーワードを使用しません。
For instance, failable initializers are implemented for numeric type conversions. To ensure conversion between numeric types maintains the value exactly, use the init(exactly:)
initializer. If the type conversion can’t maintain the value, the initializer fails.
たとえば、失敗可能なイニシャライザは数値型変換用に実装されています。 数値型間の変換で値が正確に維持されるようにするには、init(exactly:)
イニシャライザを使用します。 型変換で値を維持できない場合、イニシャライザは失敗します。
let wholeNumber: Double = 12345.0
let pi = 3.14159
if let valueMaintained = Int(exactly: wholeNumber) {
print("\(wholeNumber) conversion to Int maintains value of \(valueMaintained)")
}
// Prints "12345.0 conversion to Int maintains value of 12345"
let valueChanged = Int(exactly: pi)
// valueChanged is of type Int?, not Int
if valueChanged == nil {
print("\(pi) conversion to Int doesn't maintain value")
}
// Prints "3.14159 conversion to Int doesn't maintain value"
The example below defines a structure called Animal
, with a constant String
property called species
. The Animal
structure also defines a failable initializer with a single parameter called species
. This initializer checks if the species
value passed to the initializer is an empty string. If an empty string is found, an initialization failure is triggered. Otherwise, the species
property’s value is set, and initialization succeeds:
以下の例では、Animal
という構造体と、species
という定数 String
プロパティを定義しています。 Animal
構造体は、species
と呼ばれる単一のパラメータを持つ失敗可能なイニシャライザも定義します。 このイニシャライザは、イニシャライザに渡されたspecies
の値が空の文字列かどうかを確認します。 空の文字列が見つかった場合、初期化エラーがトリガーされます。 それ以外の場合、species
のプロパティの値が設定され、初期化は成功します。
struct Animal {
let species: String
init?(species: String) {
if species.isEmpty { return nil }
self.species = species
}
}
You can use this failable initializer to try to initialize a new Animal
instance and to check if initialization succeeded:
この失敗可能なイニシャライザを使用して、新しい Animal
インスタンスの初期化を試み、初期化が成功したかどうかを確認できます。
let someCreature = Animal(species: "Giraffe")
// someCreature is of type Animal?, not Animal
if let giraffe = someCreature {
print("An animal was initialized with a species of \(giraffe.species)")
}
// Prints "An animal was initialized with a species of Giraffe"
If you pass an empty string value to the failable initializer’s species
parameter, the initializer triggers an initialization failure:
空の文字列値を失敗可能なイニシャライザのspecies
パラメータに渡すと、イニシャライザは初期化失敗をトリガーします。
let anonymousCreature = Animal(species: "")
// anonymousCreature is of type Animal?, not Animal
if anonymousCreature == nil {
print("The anonymous creature couldn't be initialized")
}
// Prints "The anonymous creature couldn't be initialized"
Note
注釈
Checking for an empty string value (such as ""
rather than "Giraffe"
) isn’t the same as checking for nil
to indicate the absence of an optional String
value. In the example above, an empty string (""
) is a valid, non-optional String
. However, it’s not appropriate for an animal to have an empty string as the value of its species
property. To model this restriction, the failable initializer triggers an initialization failure if an empty string is found.
空の文字列値("Giraffe"
ではなく ""
など)をチェックすることは、オプションのString
値が存在しないことを示す nil
をチェックすることと同じではありません。 上の例では、空の文字列(""
)は有効なオプションではないString
です。 ただし、動物のspecies
プロパティの値として空の文字列を持つことは適切ではありません。 この制限をモデル化するために、failable イニシャライザは、空の文字列が見つかった場合に初期化失敗をトリガーします。
Failable Initializers for Enumerations
列挙型の失敗可能なイニシャライザ
You can use a failable initializer to select an appropriate enumeration case based on one or more parameters. The initializer can then fail if the provided parameters don’t match an appropriate enumeration case.
失敗可能なイニシャライザを使用すると、1 つ以上のパラメータに基づいて適切な列挙ケースを選択できます。 指定されたパラメーターが適切な列挙ケースと一致しない場合、イニシャライザーは失敗する可能性があります。
The example below defines an enumeration called TemperatureUnit
, with three possible states (kelvin
, celsius
, and fahrenheit
). A failable initializer is used to find an appropriate enumeration case for a Character
value representing a temperature symbol:
以下の例では、3 つの可能な状態 (kelvin
、celsius
、fahrenheit
) を含む、TemperatureUnit
という列挙体を定義しています。 失敗可能なイニシャライザは、温度記号を表すCharacter
値の適切な列挙ケースを見つけるために使用されます。
enum TemperatureUnit {
case kelvin, celsius, fahrenheit
init?(symbol: Character) {
switch symbol {
case "K":
self = .kelvin
case "C":
self = .celsius
case "F":
self = .fahrenheit
default:
return nil
}
}
}
You can use this failable initializer to choose an appropriate enumeration case for the three possible states and to cause initialization to fail if the parameter doesn’t match one of these states:
この失敗可能なイニシャライザを使用すると、考えられる 3 つの状態に対して適切な列挙ケースを選択し、パラメータがこれらの状態のいずれかに一致しない場合に初期化を失敗させることができます。
let fahrenheitUnit = TemperatureUnit(symbol: "F")
if fahrenheitUnit != nil {
print("This is a defined temperature unit, so initialization succeeded.")
}
// Prints "This is a defined temperature unit, so initialization succeeded."
let unknownUnit = TemperatureUnit(symbol: "X")
if unknownUnit == nil {
print("This isn't a defined temperature unit, so initialization failed.")
}
// Prints "This isn't a defined temperature unit, so initialization failed."
Failable Initializers for Enumerations with Raw Values
生の値を含む列挙型の失敗可能なイニシャライザ
Enumerations with raw values automatically receive a failable initializer, init?(rawValue:)
, that takes a parameter called rawValue
of the appropriate raw-value type and selects a matching enumeration case if one is found, or triggers an initialization failure if no matching value exists.
生の値を含む列挙型は、失敗可能なイニシャライザ init?(rawValue:)
を自動的に受け取ります。これは、適切な生の値型の rawValue
というパラメータを受け取り、一致する列挙型ケースが見つかった場合はそれを選択し、一致する値がない場合は初期化エラーをトリガーします。 存在します。
You can rewrite the TemperatureUnit
example from above to use raw values of type Character
and to take advantage of the init?(rawValue:)
initializer:
上記の TemperatureUnit
の例を書き換えて、Character
型の生の値を使用し、init?(rawValue:)
イニシャライザを利用することができます。
enum TemperatureUnit: Character {
case kelvin = "K", celsius = "C", fahrenheit = "F"
}
let fahrenheitUnit = TemperatureUnit(rawValue: "F")
if fahrenheitUnit != nil {
print("This is a defined temperature unit, so initialization succeeded.")
}
// Prints "This is a defined temperature unit, so initialization succeeded."
let unknownUnit = TemperatureUnit(rawValue: "X")
if unknownUnit == nil {
print("This isn't a defined temperature unit, so initialization failed.")
}
// Prints "This isn't a defined temperature unit, so initialization failed."
Propagation of Initialization Failure
初期化失敗の伝播
A failable initializer of a class, structure, or enumeration can delegate across to another failable initializer from the same class, structure, or enumeration. Similarly, a subclass failable initializer can delegate up to a superclass failable initializer.
クラス、構造体、または列挙体の Failable イニシャライザは、同じクラス、構造体、または列挙体の別の Failable イニシャライザに委任できます。 同様に、サブクラスのフェイル可能イニシャライザは、スーパークラスのフェイル可能イニシャライザに委任できます。
In either case, if you delegate to another initializer that causes initialization to fail, the entire initialization process fails immediately, and no further initialization code is executed.
どちらの場合も、初期化の失敗を引き起こす別のイニシャライザにデリゲートすると、初期化プロセス全体が即座に失敗し、それ以上の初期化コードは実行されません。
Note
注釈
A failable initializer can also delegate to a nonfailable initializer. Use this approach if you need to add a potential failure state to an existing initialization process that doesn’t otherwise fail.
失敗可能なイニシャライザは、失敗しないイニシャライザに委任することもできます。 このアプローチは、他の方法では失敗しない既存の初期化プロセスに潜在的な失敗状態を追加する必要がある場合に使用します。
The example below defines a subclass of Product
called CartItem
. The CartItem
class models an item in an online shopping cart. CartItem
introduces a stored constant property called quantity
and ensures that this property always has a value of at least 1
:
以下の例では、CartItem
という Product
のサブクラスを定義しています。 CartItem
クラスは、オンライン ショッピング カート内の商品をモデル化します。 CartItem
は、quantity
と呼ばれる保存された定数プロパティを導入し、このプロパティが常に少なくとも 1
の値を持つようにします。
class Product {
let name: String
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
class CartItem: Product {
let quantity: Int
init?(name: String, quantity: Int) {
if quantity < 1 { return nil }
self.quantity = quantity
super.init(name: name)
}
}
The failable initializer for CartItem
starts by validating that it has received a quantity
value of 1
or more. If the quantity
is invalid, the entire initialization process fails immediately and no further initialization code is executed. Likewise, the failable initializer for Product
checks the name
value, and the initializer process fails immediately if name
is the empty string.
CartItem
の失敗可能なイニシャライザは、1
以上のquantity
値を受け取ったかどうかを検証することから始まります。 quantity
が無効な場合、初期化プロセス全体が即座に失敗し、それ以上の初期化コードは実行されません。 同様に、Product
の失敗可能なイニシャライザは name
値をチェックし、name
が空の文字列の場合、イニシャライザ プロセスは直ちに失敗します。
If you create a CartItem
instance with a nonempty name and a quantity of 1
or more, initialization succeeds:
空ではない名前と 1
以上の数量を指定して CartItem
インスタンスを作成すると、初期化は成功します。
if let twoSocks = CartItem(name: "sock", quantity: 2) {
print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)")
}
// Prints "Item: sock, quantity: 2"
If you try to create a CartItem
instance with a quantity
value of 0
, the CartItem
initializer causes initialization to fail:
quantity
値が 0
の CartItem
インスタンスを作成しようとすると、CartItem
イニシャライザにより初期化が失敗します。
if let zeroShirts = CartItem(name: "shirt", quantity: 0) {
print("Item: \(zeroShirts.name), quantity: \(zeroShirts.quantity)")
} else {
print("Unable to initialize zero shirts")
}
// Prints "Unable to initialize zero shirts"
Similarly, if you try to create a CartItem
instance with an empty name
value, the superclass Product
initializer causes initialization to fail:
同様に、空のname
値を使用して CartItem
インスタンスを作成しようとすると、スーパークラスの Product
イニシャライザーによって初期化が失敗します。
if let oneUnnamed = CartItem(name: "", quantity: 1) {
print("Item: \(oneUnnamed.name), quantity: \(oneUnnamed.quantity)")
} else {
print("Unable to initialize one unnamed product")
}
// Prints "Unable to initialize one unnamed product"
Overriding a Failable Initializer
失敗可能なイニシャライザのオーバーライド
You can override a superclass failable initializer in a subclass, just like any other initializer. Alternatively, you can override a superclass failable initializer with a subclass nonfailable initializer. This enables you to define a subclass for which initialization can’t fail, even though initialization of the superclass is allowed to fail.
他のイニシャライザと同様に、サブクラス内のスーパークラスの失敗可能なイニシャライザをオーバーライドできます。 あるいは、スーパークラスの失敗可能なイニシャライザをサブクラスの失敗しないイニシャライザでオーバーライドすることもできます。 これにより、スーパークラスの初期化が失敗することが許容される場合でも、初期化が失敗できないサブクラスを定義できます。
Note that if you override a failable superclass initializer with a nonfailable subclass initializer, the only way to delegate up to the superclass initializer is to force-unwrap the result of the failable superclass initializer.
失敗可能なスーパークラスイニシャライザを失敗しないサブクラスイニシャライザでオーバーライドする場合、スーパークラスイニシャライザに委任する唯一の方法は、失敗可能なスーパークラスイニシャライザの結果を強制的にアンラップすることであることに注意してください。
Note
注釈
You can override a failable initializer with a nonfailable initializer but not the other way around.
失敗可能なイニシャライザを失敗しないイニシャライザでオーバーライドすることはできますが、その逆はできません。
The example below defines a class called Document
. This class models a document that can be initialized with a name
property that’s either a nonempty string value or nil
, but can’t be an empty string:
以下の例では、Document
というクラスを定義しています。 このクラスは、空ではない文字列値または nil
のname
プロパティで初期化できるドキュメントをモデル化しますが、空の文字列にすることはできません。
class Document {
var name: String?
// this initializer creates a document with a nil name value
init() {}
// this initializer creates a document with a nonempty name value
init?(name: String) {
if name.isEmpty { return nil }
self.name = name
}
}
The next example defines a subclass of Document
called AutomaticallyNamedDocument
. The AutomaticallyNamedDocument
subclass overrides both of the designated initializers introduced by Document
. These overrides ensure that an AutomaticallyNamedDocument
instance has an initial name
value of "[Untitled]"
if the instance is initialized without a name, or if an empty string is passed to the init(name:)
initializer:
次の例では、AutomaticallyNamedDocument
という Document
のサブクラスを定義します。 AutomaticallyNamedDocument
サブクラスは、Document
によって導入された指定イニシャライザを両方ともオーバーライドします。 これらのオーバーライドにより、インスタンスが名前なしで初期化される場合、または空の文字列が init(name:)
イニシャライザに渡される場合、AutomaticallyNamedDocument
インスタンスの初期name
値が "[Untitled]"
になることが保証されます。
class AutomaticallyNamedDocument: Document {
override init() {
super.init()
self.name = "[Untitled]"
}
override init(name: String) {
super.init()
if name.isEmpty {
self.name = "[Untitled]"
} else {
self.name = name
}
}
}
The AutomaticallyNamedDocument
overrides its superclass’s failable init?(name:)
initializer with a nonfailable init(name:)
initializer. Because AutomaticallyNamedDocument
copes with the empty string case in a different way than its superclass, its initializer doesn’t need to fail, and so it provides a nonfailable version of the initializer instead.
AutomaticallyNamedDocument
は、スーパークラスの失敗可能な init?(name:)
イニシャライザを失敗しない init(name:)
イニシャライザでオーバーライドします。 AutomaticallyNamedDocument
は、そのスーパークラスとは異なる方法で空の文字列のケースに対処するため、その初期化子が失敗する必要はなく、その代わりに失敗しないバージョンの初期化子を提供します。
You can use forced unwrapping in an initializer to call a failable initializer from the superclass as part of the implementation of a subclass’s nonfailable initializer. For example, the UntitledDocument
subclass below is always named "[Untitled]"
, and it uses the failable init(name:)
initializer from its superclass during initialization.
イニシャライザで強制アンラップを使用すると、サブクラスの失敗しないイニシャライザの実装の一部として、スーパークラスから失敗可能なイニシャライザを呼び出すことができます。 たとえば、以下の UntitledDocument サブクラスの名前は常に「[Untitled]」であり、初期化中にスーパークラスの失敗可能な init(name:) イニシャライザを使用します。
class UntitledDocument: Document {
override init() {
super.init(name: "[Untitled]")!
}
}
In this case, if the init(name:)
initializer of the superclass were ever called with an empty string as the name, the forced unwrapping operation would result in a runtime error. However, because it’s called with a string constant, you can see that the initializer won’t fail, so no runtime error can occur in this case.
この場合、スーパークラスの init(name:)
イニシャライザが名前として空の文字列を使用して呼び出された場合、強制的なアンラップ操作により実行時エラーが発生します。 ただし、文字列定数を使用して呼び出されるため、イニシャライザは失敗しないことがわかり、この場合は実行時エラーは発生しません。
The init! Failable Initializer
init! 失敗可能なイニシャライザ
You typically define a failable initializer that creates an optional instance of the appropriate type by placing a question mark after the init
keyword (init?
). Alternatively, you can define a failable initializer that creates an implicitly unwrapped optional instance of the appropriate type. Do this by placing an exclamation point after the init
keyword (init!
) instead of a question mark.
通常、init
キーワード (init?
) の後に疑問符を置くことで、適切な型のオプションのインスタンスを作成する失敗可能なイニシャライザを定義します。 あるいは、適切な型の暗黙的にアンラップされたオプションのインスタンスを作成する失敗可能なイニシャライザを定義することもできます。 これを行うには、init
キーワード(init!
)の後に疑問符の代わりに感嘆符を置きます。
You can delegate from init?
to init!
and vice versa, and you can override init?
with init!
and vice versa. You can also delegate from init
to init!
, although doing so will trigger an assertion if the init!
initializer causes initialization to fail.
init?
からinit!
へ委任できます 。 その逆も同様で、init?
をinit!
でオーバーライドできます。 逆もしかりです。 init
から init!
に委任することもできますが、もし init!
初期化子により初期化が失敗すると、 アサーションがトリガーされます。
Required Initializers
必要なイニシャライザ
Write the required
modifier before the definition of a class initializer to indicate that every subclass of the class must implement that initializer:
クラス初期化子の定義の前にrequired
修飾子を記述して、クラスのすべてのサブクラスがその初期化子を実装する必要があることを示します。
class SomeClass {
required init() {
// initializer implementation goes here
}
}
You must also write the required
modifier before every subclass implementation of a required initializer, to indicate that the initializer requirement applies to further subclasses in the chain. You don’t write the override
modifier when overriding a required designated initializer:
また、必須のイニシャライザのすべてのサブクラス実装の前に、イニシャライザの要件が連鎖内のさらなるサブクラスに適用されることを示すために、required
修飾子を記述する必要があります。 必須の指定イニシャライザをオーバーライドする場合は、override
修飾子を記述しません。
class SomeSubclass: SomeClass {
required init() {
// subclass implementation of the required initializer goes here
}
}
Note
注釈
You don’t have to provide an explicit implementation of a required initializer if you can satisfy the requirement with an inherited initializer.
継承されたイニシャライザで要件を満たすことができる場合は、必要なイニシャライザの明示的な実装を提供する必要はありません。
Setting a Default Property Value with a Closure or Function
クロージャまたは関数を使用したデフォルトのプロパティ値の設定
If a stored property’s default value requires some customization or setup, you can use a closure or global function to provide a customized default value for that property. Whenever a new instance of the type that the property belongs to is initialized, the closure or function is called, and its return value is assigned as the property’s default value.
格納されたプロパティのデフォルト値にカスタマイズや設定が必要な場合は、クロージャまたはグローバル関数を使用して、そのプロパティにカスタマイズされたデフォルト値を提供できます。 プロパティが属する型の新しいインスタンスが初期化されるたびに、クロージャまたは関数が呼び出され、その戻り値がプロパティのデフォルト値として割り当てられます。
These kinds of closures or functions typically create a temporary value of the same type as the property, tailor that value to represent the desired initial state, and then return that temporary value to be used as the property’s default value.
これらの種類のクロージャまたは関数は通常、プロパティと同じ型の一時的な値を作成し、その値を目的の初期状態を表すように調整してから、プロパティのデフォルト値として使用する一時的な値を返します。
Here’s a skeleton outline of how a closure can be used to provide a default property value:
以下は、クロージャを使用してデフォルトのプロパティ値を提供する方法の概略です。
class SomeClass {
let someProperty: SomeType = {
// create a default value for someProperty inside this closure
// someValue must be of the same type as SomeType
return someValue
}()
}
Note that the closure’s end curly brace is followed by an empty pair of parentheses. This tells Swift to execute the closure immediately. If you omit these parentheses, you are trying to assign the closure itself to the property, and not the return value of the closure.
クロージャの終わりの中括弧の後に空の括弧が続いていることに注意してください。 これにより、Swift にクロージャーをただちに実行するように指示されます。 これらの括弧を省略すると、クロージャの戻り値ではなく、クロージャ自体をプロパティに割り当てようとします。
Note
注釈
If you use a closure to initialize a property, remember that the rest of the instance hasn’t yet been initialized at the point that the closure is executed. This means that you can’t access any other property values from within your closure, even if those properties have default values. You also can’t use the implicit self
property, or call any of the instance’s methods.
クロージャを使用してプロパティを初期化する場合は、クロージャが実行された時点ではインスタンスの残りの部分がまだ初期化されていないことに注意してください。 これは、たとえそれらのプロパティにデフォルト値があるとしても、クロージャ内から他のプロパティ値にアクセスできないことを意味します。 また、暗黙的な self
プロパティを使用したり、インスタンスのメソッドを呼び出したりすることもできません。
The example below defines a structure called Chessboard
, which models a board for the game of chess. Chess is played on an 8 x 8 board, with alternating black and white squares.
以下の例では、チェスのゲーム用のボードをモデル化する Chessboard
という構造を定義します。 チェスは、黒と白の正方形が交互に配置された 8 x 8 のボード上でプレイされます。
To represent this game board, the Chessboard
structure has a single property called boardColors
, which is an array of 64 Bool
values. A value of true
in the array represents a black square and a value of false
represents a white square. The first item in the array represents the top left square on the board and the last item in the array represents the bottom right square on the board.
このゲーム ボードを表すために、Chessboard
構造には、64 個のBool
値の配列である、boardColors
と呼ばれる単一のプロパティがあります。 配列内の値 true
は黒い四角形を表し、値 false
は白い四角形を表します。 配列の最初の項目はボードの左上の正方形を表し、配列の最後の項目はボードの右下の正方形を表します。
The boardColors
array is initialized with a closure to set up its color values:
boardColors
配列は、色の値を設定するためにクロージャで初期化されます。
struct Chessboard {
let boardColors: [Bool] = {
var temporaryBoard: [Bool] = []
var isBlack = false
for i in 1...8 {
for j in 1...8 {
temporaryBoard.append(isBlack)
isBlack = !isBlack
}
isBlack = !isBlack
}
return temporaryBoard
}()
func squareIsBlackAt(row: Int, column: Int) -> Bool {
return boardColors[(row * 8) + column]
}
}
Whenever a new Chessboard
instance is created, the closure is executed, and the default value of boardColors
is calculated and returned. The closure in the example above calculates and sets the appropriate color for each square on the board in a temporary array called temporaryBoard
, and returns this temporary array as the closure’s return value once its setup is complete. The returned array value is stored in boardColors
and can be queried with the squareIsBlackAt(row:column:)
utility function:
新しいChessboard
インスタンスが作成されるたびにクロージャが実行され、boardColors
のデフォルト値が計算されて返されます。 上の例のクロージャは、ボード上の各正方形に適切な色を計算して、temporaryBoard
という一時配列に設定し、セットアップが完了すると、この一時配列をクロージャの戻り値として返します。 返された配列値はboardColors
に保存され、squareIsBlackAt(row:column:)
ユーティリティ関数でクエリできます。
let board = Chessboard()
print(board.squareIsBlackAt(row: 0, column: 1))
// Prints "true"
print(board.squareIsBlackAt(row: 7, column: 7))
// Prints "false"