Swift 6.0 beta 日本語化計画 : Swift 6.0 beta
型
Swift では、型には2種類あります:名前付きの型と複合型です。名前付きの型 は、それが定義されるときに、特定の名前を付けることができる型です。名前付きの型には、クラス、構造体、列挙型、およびプロトコルが含まれます。たとえば、MyClass という名前のユーザー定義のクラスのインスタンスは、MyClass 型です。ユーザー定義の名前付きの型に加えて、Swift 標準ライブラリは、配列、辞書、および optional の値を表すものも含めて、多くの一般的に使用される名前付きの型を定義しています。
通常他の言語で基本的なまたは原始的と考えられているデータ型は、数字、文字、そして文字列を表現する型のように、それらは実際には、名前付きの型であり、構造体を使用して Swift 標準ライブラリで定義され、実装されています。それらは名前付きの型なので、拡張機能 と 拡張機能の宣言 で述べたように、拡張機能の宣言を使用して、プログラムのニーズに合わせて動作を拡張できます。
複合型 は、Swift 言語自体で定義された名前のない型です。関数型とタプル型の2つの複合型があります。複合型は、名前付きの型および他の複合型を含みます。例えば、タプル型 (Int, (Int, Int)) は2つの要素を含みます。最初は、名前付きの Int 型であり、第二は、他の複合型 (Int, Int) です。
名前付きの型または複合型のまわりに括弧を付けることができます。ただし、型の周りに括弧を追加しても効果はありません。たとえば、(Int) は Int と等価です。
この章では、Swift 言語自体で定義された型について議論し、Swift の型推論の動作について説明します。
型注釈 は、明示的に変数や式の型を指定します。以下の例のように、型注釈は、コロン (:) で始まり、型で終わります:
最初の例では、式 someTuple はタプル型 (Double, Double) を持つように指定されています。第二の例では、関数 someFunction へのパラメータ a が Int 型を持つように指定されています。
型注釈は、型の前の型属性のオプションのリストを含む事ができます。
型識別子 は、名前付きの型または複合型の、名前付きの型または型エイリアスのいずれかを参照します。
ほとんどの場合、型識別子は識別子と同じ名前を持つ名前付きの型を直接参照します。たとえば、Int は直接 Int の名前付きの型を参照する型識別子であり、また型識別子 Dictionary<String, Int> は、直接名前付きの型 Dictionary<String, Int> を参照します。
型識別子が同じ名前の型を参照しない2つの場合があります。最初の場合は、型識別子が名前付きの型または複合型の、型エイリアスを参照する場合です。たとえば、以下の例では、型注釈における Point の使用はタプル型 (Int, Int) を参照します。
第二の場合は、型識別子は、他のモジュールで宣言されたか、または他の型の中で入れ子になった名前付きの型を参照するために、ドット (.) 構文を使用する場合です。たとえば、以下のコードの型識別子は ExampleModule のモジュール内で宣言された名前付きの型 MyType を参照します。
タプル型は、括弧で囲まれた、カンマ区切りの型のリストです。
複数の値を含む一つのタプルを返す事を関数に許可するには、関数の戻り値の型としてタプル型を使用できます。また、タプル型の要素に名前を付け、個々の要素の値を参照するためにそれらの名前を使用する事ができます。要素名は、識別子の直後にコロン (:) を続けて構成されます。これらの機能の両方の例を見るには、複数の戻り値を持つ関数 を参照してください。
タプル型の要素が名前を持っている場合、その名前は、型の一部です。
すべてのタプル型は、空のタプル型 ( ) の型エイリアスである Void を除いて、2つ以上の型を含んでいます。
関数型 は、関数、メソッド、またはクロージャの型を表し、矢印 (->) で区切られたパラメータと戻り値の型で構成されています:
(<#parameter type#>) -> <#return type#>
パラメータ型 は、型のカンマ区切りされたリストです。戻り値の型 は、タプル型にできるので、関数型は、複数の値を返す関数やメソッドをサポートしています。
関数型のパラメータ ( ) -> T (ここで T は任意の型) は暗黙のうちにその呼び出す場所でクロージャを作成するため autoclosure 属性を適用できます。これは、関数を呼び出すときに、明示的なクロージャを書く事を必要とせずに式の評価を延期する、構文的に便利な方法を提供します。autoclosure 関数型パラメータの例については、オートクロージャ を参照してください。
関数型は、その パラメータ型 内に可変引数パラメータを持つことができます。構文的には、可変引数パラメータは、基本型名で構成され、Int... のように3つのドット(...) が直後に続きます。可変引数パラメータは、基本型名の要素を含む配列として扱われます。例えば、可変引数パラメータ Int... は、[INT] として扱われます。可変引数パラメータを使用する例については、可変引数パラメータ を参照してください。
in-out パラメータを指定するには、inout キーワードをパラメータ型の前に接頭辞として付けます。inout キーワードで可変引数のパラメータや戻り値の型をマークすることはできません。in-out パラメータは、In-Out パラメータ で説明されています。
関数型が 1 つのパラメータしか持たず、そのパラメータ型がタプル型である場合、その関数型を書くときにタプル型は括弧で囲まなければなりません。たとえば、((Int,Int)) -> Void は、タプル型 (Int,Int) の単一のパラメータを取り、値を返さない関数型です。対照的に、括弧なしでは、(Int,Int) -> Void は、2 つの Int パラメータを取り、値を返さない関数型です。同様に、Void は ( ) の型エイリアスであるため、関数型 (Void) -> Void は空のタプルである単一の引数を取る関数 (( )) -> ( ) と同じです。これらの型は ( ) -> ( ) の引数をとらない関数と同じではありません。
関数及びメソッド内の引数名は、対応する関数型の一部ではありません。例えば:
引数のラベルは関数型の一部ではないので、関数型を記述する際には省略できます。
関数型が、一つ以上の矢印(->) を含んでいる場合は、関数型は、右から左にグループ化されます。例えば、関数型 (Int) -> (Int) ->Int は (Int) -> ((Int) -> Int) として理解されます。つまり、Int を取り、Int を取って返す別の関数を返す関数です。
エラーを throw または rethrow できる関数の型は、throws キーワードを含まなければなりません。throws の後に括弧で囲んだ型を含めると、関数が throws するエラーの型を指定できます。throw エラーの型は Error プロトコルに準拠していなければなりません。型を指定せずに throws を記述することは、throws(any Error) を記述することと同じです。throws を省略することは、throws(Never) を記述することと同じです。関数が throws するエラーの型は、ジェネリック型、ボックス化されたプロトコル型、不透明型など、Error に準拠する任意の型にすることができます。
関数が throws するエラーの型はその関数の型の一部であり、エラー型間のサブタイプ関係は、対応する関数型もサブタイプであることを意味します。たとえば、カスタムの MyError 型を宣言する場合、一部の関数型間の関係は、スーパータイプからサブタイプまで以下のようになります。
これらのサブタイプの関係の結果として、以下のようになります。
関連型または汎用型パラメータを関数型内で thrown されるエラー型として使用する場合、その関連型または汎用型パラメータは暗黙的に Error プロトコルに準拠する必要があります。
throw する関数と rethrow する関数は、Throw する関数とメソッド および Rethrow する関数とメソッド で説明しています。
非同期関数の関数型は、async キーワードでマークしなければなりません。async キーワードは関数型の一部であり、同期関数は非同期関数のサブタイプです。その結果、同期関数を非同期関数と同じ場所で使用できます。非同期関数の詳細については、非同期関数とメソッド を参照してください。
エスケープされていない関数であるパラメータは、Any 型のプロパティ、変数、または定数に格納できません。これは、値がエスケープされる可能性があるためです。
エスケープされていない関数であるパラメータは、別のエスケープをしない関数パラメータに引数として渡すことはできません。この制限により、実行時ではなくコンパイル時にメモリへのアクセスの競合を多く Swift がチェックできます。例えば:
上に挙げたコードでは、takesTwoFunctions(first:second:) への両方のパラメータが関数です。いずれのパラメータも @escaping とマークされていないので、いずれも結果としてエスケープされていません。
上に挙げた例で "Error" とマークされた 4 つの関数呼び出しは、コンパイラエラーを引き起こします。first と second のパラメータはエスケープされていない関数なので、別のエスケープされていない関数パラメータに引数として渡すことはできません。対照的に、"OK" とマークされた 2 つの関数呼び出しはコンパイラエラーを引き起こしません。これらの関数呼び出しは、external が takesTwoFunctions(first:second:) のパラメータの 1 つではないため、制限に違反しません。
この制限を回避する必要がある場合は、パラメータの 1 つを escaping としてマークするか、または、 withoutActuallyEscaping(_:do:) 関数を使用してエスケープする関数にエスケープしない関数パラメータの 1 つを一時的に変換します。メモリへのアクセスの競合を回避する方法については、メモリの安全性 を参照してください。
Swift 言語は Swift 標準ライブラリの Array<Element> 型について、以下のシンタックスシュガーを提供しています。
[<#type#>]
言い換えると、以下の2つの宣言は等価です。
どちらの場合も、定数の someArray は文字列の配列として宣言されています。配列の要素は、角括弧内の有効なインデックス値を指定することで、サブスクリプトを使用してアクセスできます:someArray[0] は、インデックス 0 の、"Alex" の要素を参照しています:
要素の基本型の名前は角括弧の最も内側のペアの中に含まれており、角括弧のペアを入れ子にすることで、多次元配列を作成できます。たとえば、角括弧の3つのセットを使用して、整数の3次元配列を作成できます。
多次元配列内の要素にアクセスする場合、一番左のサブスクリプト・インデックスは、最も外側の配列内のそのインデックスにある要素を参照します。次の右へのサブスクリプト・インデックスは、一つの入れ子になったレベルを入った、配列内のそのインデックスにある要素を参照します、などなど。これは、上記の例では、array3D[0] は [[1, 2], [3, 4]] を参照し、array3D[0][1] は、 [3,4] を参照し、また array3D[0][1][1] は値4を参照する事を意味します。
Swift 標準ライブラリの Array 型の詳細な議論については、配列 を参照してください。
Swift 言語は Swift 標準ライブラリの Dictionary<Key, Value> 型について、以下のシンタックスシュガーを提供しています。
[<#key type#>: <#value type#>]
言い換えると、以下の2つの宣言は等価です。
どちらの場合も、定数の someDictionary は、キーとして文字列を、値として整数を持つ辞書として宣言されています。
辞書の値は、角括弧の中に対応するキーを指定し、サブスクリプトを使用してアクセスできます: someDictionary["Alex"] は、キー "Alex" に関連した値を参照しています。サブスクリプトは、辞書の値型の optional の値を返します。指定されたキーが辞書に含まれていない場合は、サブスクリプトは nil を返します。
辞書のキー型は、Swift 標準ライブラリの Hashable プロトコルに準拠しなければなりません。
Swift 標準ライブラリの Dictionary 型の詳細な議論については、Dictionary を参照してください。
Swift 言語は接尾辞 ? を、Optional<Wrapped> という名前の型でシンタックスシュガーとして定義しており、それは Swift 標準ライブラリで定義されています。言い換えると、以下の2つの宣言は等価です:
どちらの場合も、変数 optionalInteger は optional の整数の型を持つように宣言されています。型と ? の間に空白がない事に注意して下さい。
型 Optional<Wrapped> は、存在してもしなくてもよい値を表すために使用される2つのケース、none 及び some(Wrapped) から成る列挙型です。すべての型は、明示的に (または暗黙にそれに変換される) optional の型であると宣言されます。optional の変数またはプロパティを宣言するときに初期値を指定しない場合、その値は自動的にデフォルトで nil になります。
optional の型のインスタンスが値を含んでいる場合は、以下に示すように、接尾辞演算子 ! を使用してその値にアクセスできます:
! 演算子を使用して、nil の値を持つ optional を開封すると、実行時エラーが起こります。
また、条件付きで optional の式で演算を実行するには、optional の連鎖と optional の結合も使用できます。値が nil の場合、何も演算は行われないため、実行時エラーは起こりません。
詳細および、optional の型を使用する方法を示す例については、Optionals を参照してください。
Swift 言語は、接尾辞 ! を、Optional<Wrapped> の名前付きの型のシンタックスシュガーとして定義しており、それは Swift 標準ライブラリで定義されていて、それがアクセスされたときに、自動的に開封されるという動作が追加されています。nil の値を持つ暗黙的に開封された optional を使用しようとすると、実行時エラーが発生します。暗黙の開封動作を例外として、以下の 2 つの宣言は等価です。
型と ! との間に空白が全くないことに注意してください。
暗黙の開封は、その型を含む宣言の意味を変化させるため、タプル型または汎用型の中に入れ子にされた optional 型、例えば辞書や配列の要素型は、暗黙的に開封されたとしてマークすることはできません。 例えば:
暗黙的に開封された optional は同じ optional<Wrapped> 型を optional の値として持っているので、optional を使用できるあなたのコード内のすべての同じ場所で暗黙的に開封された optional を使用できます。たとえば、変数、定数、および optional のプロパティに暗黙的に開封された optional の値を割り当てる事ができ、またその逆ができます。
optional と同様に、暗黙的に開封された optional の変数またはプロパティを宣言する時に初期値を指定しない場合は、その値は自動的にデフォルトで nil になります。
条件付きで、暗黙的に開封された optional の式で演算を実行するには、optional の連鎖を使用してください。値が nil の場合、演算は何も行われないため、実行時エラーは全く起こりません。
暗黙的に開封された optional の型の詳細については、暗黙に開封された Optionals を参照してください。
プロトコルを構成する型 は、指定されたプロトコルのリスト内の各プロトコルに準拠する型、または与えられたクラスのサブクラスであり、指定されたプロトコルのリスト内の各プロトコルに準拠する型を定義します。プロトコルを構成する型は、型注釈、汎用パラメータ句、および汎用 where 句で型を指定する場合にのみ使用できます。
プロトコルを構成する型は以下の形式です:
<#Protocol 1#> & Protocol 2#>
プロトコルを構成する型は、型を準拠させたい各プロトコルから継承する新しい、名前の付いたプロトコルを明示的に定義することなく、複数のプロトコルの要件に準拠する型の値を指定することができます。例えば、ProtocolA,ProtocolB および ProtocolC から継承する新しいプロトコルを宣言するのではなく、プロトコルを構成する型 ProtocolA & ProtocolB & ProtocolC を使用できます。同様に、SuperClass のサブクラスであり、 ProtocolA に準拠する新しいプロトコルを宣言する代わりに、SuperClass & ProtocolA を使用することができます。
プロトコルを構成するリストの各項目は、以下のうち1つです。リストには最大で 1 つのクラスを含めることができます。
プロトコルを構成する型に型エイリアスが含まれる場合、同じプロトコルが定義内に一つ以上表示される事は可能であり、重複は無視されます。たとえば、以下のコードの PQR の定義は P & Q & R と同等です。
不透明型 は、基になる具体的な型を指定せずに、プロトコルまたはプロトコル構成に準拠する型を定義します。
不透明型は、関数またはサブスクリプトの戻り値の型、またはプロパティの型として表示されます。不透明型は、配列の要素型や optional の包まれた型などのタプル型または汎用型の一部として表示できません。
不透明型の形式は次のとおりです。
some <#constraint#>
制約 (constraint) は、クラス型、プロトコル型、プロトコル構成型、または Any です。 値は、リストされたプロトコルまたはプロトコル構成に準拠するか、リストされたクラスから継承する型のインスタンスである場合にのみ、不透明型のインスタンスとして使用できます。不透明な値を操作するコードは、制約 によって定義されたインターフェイスの一部である方法でのみ値を使用できます。
コンパイル時に、不透明な型の値には特定の具体的な型があり、Swift はその基礎となる型を最適化に使用できます。ただし、不透明な型は、その基礎となる型に関する情報が越えられない境界を形成します。
プロトコル宣言には不透明型を含めることはできません。クラスは、final でないメソッドの戻り値の型として不透明型を使用する事はできません。
不透明型を戻り値の型として使用する関数は、単一の基礎となる型を共有する値を返さなければなりません。戻り値の型には、関数の汎用型パラメータの一部である型を含めることができます。たとえば、関数 someFunction<T>( ) は、型 T または Dictionary<String,T> の値を返すことができます。
ボックス化されたプロトコル型 は、プロトコルまたはプロトコル構成に準拠する型を定義し、プログラムの実行中にその準拠型が変化する機能を備えています。
ボックス化されたプロトコル型の形式は以下のとおりです。
制約 (constraint) は、プロトコル型、プロトコル合成型、プロトコル型のメタタイプ、またはプロトコル合成型のメタタイプです。
実行時に、ボックス化されたプロトコル型のインスタンスには、制約 を満たす任意の型の値を含めることができます。この動作は、コンパイル時に特定の準拠型がわかっている不透明型の動作とは対照的です。ボックス化されたプロトコル型を操作するときに使用される追加の間接レベルは、:newTerm:boxing と呼ばれます。ボックス化では通常、記憶装置用の個別のメモリ割り当てとアクセス用の追加の間接レベルが必要になり、実行時にパフォーマンスコストが発生します。
Any または AnyObject 型に any を適用しても効果はありません。これらの型はすでにボックス化されたプロトコル型であるためです。
メタタイプ型 は、クラス型、構造体型、列挙型、及びプロトコル型を含む全ての型を参照します。
クラス、構造体、または列挙型のメタタイプは、その型の名前の後、.Type が続きます。プロトコル型のメタタイプー実行時のプロトコルに準拠する、具体的な型ではないーは、そのプロトコルの名前の後 .Protocol が続きます。例えば、クラス型 SomeClass のメタタイプは SomeClass.Type で、プロトコル SomeProtocol のメタタイプは SomeProtocol.Protocol です。
値として型にアクセスするために、接尾辞 self の式を使用できます。たとえば、SomeClass.self は SomeClass それ自体を返し、SomeClass のインスタンスを返すのではありません。また SomeProtocol.self は SomeProtocol それ自体を返し、実行時に SomeProtocol に準拠した型のインスタンスを返すのではありません。以下の例に示すように、値として実行時の型に、そのインスタンスの dynamic にアクセスするための型のインスタンスで type(of:) 関数を呼び出す事ができます。
詳細については、Swift 標準ライブラリの type(of:) を参照してください。
その型のメタタイプ値から型のインスタンスを構築するには、イニシャライザ式を使用します。クラスインスタンスの場合、呼び出されるイニシャライザは、required キーワードでマークするか、final キーワードでクラス全体をマークしなければなりません。
Any 型には、他のすべての型の値を含めることができます。以下のいずれかの型のインスタンスの具体的な型として、Any を使用できます:
インスタンスの具体的な型として Any を使用する場合、そのプロパティまたはメソッドにアクセスする前に、インスタンスを既知の型にキャストする必要があります。Any の具体的な型を持つインスタンスは、元の動的 (dynamic) 型を維持し、型キャスト演算子の 1 つ (as、as?、または as!) を使用してその型にキャストできます。たとえば、as? を使って、以下のように、異種配列の最初のオブジェクトを String に条件付きでダウンキャストします。
キャストの詳細については、型キャスト を参照してください。
AnyObject プロトコルは、Any 型に似ています。すべてのクラスは暗黙的に AnyObject に準拠しています。言語によって定義される Any とは異なり、AnyObject は Swift 標準ライブラリによって定義されています。詳細については、クラス専用プロトコル と AnyObject を参照してください。
Self 型は特定の型ではなく、その型の名前を繰り返したり、知らなくても、現在の型を簡単に参照できます。
プロトコル宣言またはプロトコルメンバ宣言では、Self 型は、プロトコルに準拠する最終的な型を参照します。
構造体、クラス、または列挙型宣言内では、Self 型は宣言によって導入された型を参照します。型のメンバの宣言内では、Self 型はその型を参照します。クラス宣言のメンバでは、Self は以下のようにのみ表示されます。
例えば、以下のコードは、その戻り値の型が Self であるインスタンスメソッド f を示しています。
上記の例の最後の部分は、Self が変数自体のコンパイル時の Superclass 型ではなく、z の値の実行時の Subclass 型を参照することを示しています。
入れ子にされた型宣言内では、Self 型は、最も内側の型宣言によって導入された型を参照します。
Self 型は、Swift 標準ライブラリの type(of:) 関数と同じ型を参照します。現在の型のメンバにアクセスするための Self.someStaticMember の書き込みは、type(of:self).someStaticMember の書き込みと同じです。
型の継承句 は、名前付きの型がどのクラスから継承し、名前付きの型がどのプロトコルに準拠するかを指定するために使用されます。型の継承句は、コロン (:) で始まり、型識別子のリストが続きます。
クラス型は、一つののスーパークラスから継承し、プロトコルにいくつでも準拠することができます。クラスを定義する場合、スーパークラスの名前は、最初に型識別子のリスト内に表示され、クラスが準拠しなければならないプロトコルがいくつでも続かなければなりません。クラスが別のクラスから継承していない場合、このリストは、代わりにプロトコルで始めることができます。より深い議論とクラス継承のいくつかの例については、継承 を参照してください。
他の名前付きの型は、プロトコルのリストからのみ継承し、またはそれに準拠することができます。プロトコル型は、他のプロトコルからいくつでも継承できます。プロトコル型が他のプロトコルから継承する場合、それら他のプロトコルからの一連の要件は一緒に集約され、現在のプロトコルから継承する全ての型は、これらの要件のすべてに準拠しなければなりません。
列挙型定義における型の継承句は、プロトコルのリスト、またはその case に生の値を代入する列挙型の case では、それらの生の値の型を指定する一つの名前付きの型のいずれかです。その生の値の型を指定する、型の継承句を使用して列挙型を定義する例については、生の値 を参照してください。
Swift は、コード内で多くの変数や式の型の一部または型を省略できるように、広範囲に 型の推測 を使用します。たとえば、var x: Int = 0 と書く代わりに、var x = 0 と書いて、完全に型を省略でき、コンパイラは正しく、x の名前が Int 型の値であると推測できます。同様に、完全な型が文脈から推測できる場合も、型の一部を省略できます。たとえば、let dict: Dictionary = ["A": 1] と書く場合、コンパイラは dict は Dictionary<String, Int> の型であることを推測します。
上記の例のいずれにおいても、型の情報は、式ツリーの葉からそのルート(根) に渡されます。つまり、var x: Int = 0 の x の型は、最初 0 の型をチェックして、ルート(変数 x) まで、この型の情報を渡すことによって推測されます。
Swift では、型の情報は、反対方向にも流れますールート(根) から葉に。例えば、以下の例では、定数 eFloat 上の明示的な型注釈 (: Float) は、Double の代わりに Float の推測された型を持つ 2.71828 の数値リテラルとなります。
Swift における型推測は、一つの式または文のレベルで動作します。これは、式の中で省略された型または型の一部を推測するために必要なすべての情報は、式の型チェックまたはその部分式の一つからアクセス可能でなければならないことを意味します。