Swift 5.3 日本語化計画 : Swift 5.3


宣言



宣言 は、新しい名前を導入したり、プログラムに構築したりします。たとえば、宣言を使用して、関数やメソッドを導入したり、変数や定数を導入したり、列挙型、構造体、クラス、プロトコル型を定義したりします。また、宣言を使用して既存の名前付き型の動作を拡張したり、他の場所で宣言されているシンボルをプログラムにインポートすることもできます。


Swift では、ほとんどの宣言はまた、それらが実装されまたは宣言されたと同時に初期化されるという意味で定義でもあります。つまり、プロトコルはそのメンバを実装しないので、ほとんどのプロトコルメンバは宣言のみです。便宜上、区別は Swift では重要ではないため、宣言 の用語は、宣言と定義の両方をカバーしています。


宣言の文法

declarationimport-declaration
declarationconstant-declaration
declarationvariable-declaration
declarationtypealias-declaration
declarationfunction-declaration
declarationenum-declaration
declarationstruct-declaration
declarationclass-declaration
declarationprotocol-declaration
declarationinitializer-declaration
declarationdeinitializer-declaration
declarationextension-declaration
declarationsubscript-declaration
declarationoperator-declaration
declarationprecedence-group-declaration
declarationsdeclaration­ declarations ­opt



トップレベルのコード



Swift のソースファイル内のトップレベルのコードは、ゼロ個以上の文、宣言、および式で構成されています。デフォルトでは、ソースファイルのトップレベルで宣言されている変数、定数、および他の名前付きの宣言は、同じモジュールの一部である、すべてのソースファイル内のコードにアクセス可能です。アクセス制御レベル で説明したように、アクセスレベル修飾子で宣言をマークすることで、このデフォルトの動作をオーバーライドできます。


トップレベルのコードには、トップレベルの宣言と実行可能なトップレベルのコードの 2 種類あります。トップレベルの宣言は宣言のみで構成され、すべての Swift ソースファイルで許可されます。実行可能なトップレベルのコードには、宣言だけでなく文と式が含まれており、プログラムのトップレベルのエントリポイントとしてのみ許可されます。


実行可能ファイルを作成するためにコンパイルする Swift コードには、コードがファイルやモジュールにどのようにまとまっているかに関係なく、トップレベルのエントリポイントをマークするために以下のアプローチの最大 1 つを含めることができます:main 属性、NSApplicationMain 属性、UIApplicationMain 属性、 main.swiftファイル、またはトップレベルの実行可能コードを含むファイルです。


トップレベルの宣言の文法

top-level-declarationstatements ­opt



コードブロック



コードブロック は、一緒にグループ化した文で様々な宣言および制御構造体により使用されます。これは以下の形式です:


{
       
}



コードブロック内の は、宣言、式、および他の種類の文を含み、ソースコードでの出現順に実行されます。


コードブロックの文法

code-block{ statements ­opt ­}



Import 宣言



import 宣言 を使用すると、現在のファイルの外で宣言されたシンボルにアクセスできます。基本的な形式は、全体のモジュールを import します。それは import キーワードに続くモジュールの名前で構成されています。


import



詳細を指定すると、どのシンボルをインポートするかが制限されます。特定のサブモジュール、またはモジュールやサブモジュール内の特定の宣言を指定できます。この詳細形式を使用すると、インポートされたシンボル (およびそれを宣言するモジュールではない) のみが現在のスコープ内で使用可能になります。


import .
import .



import 宣言の文法

import-declarationattributes ­opt ­import ­import-kind ­opt ­import-path

import-kindtypealiasstructclass | enumprotocollet | varfunc
import-pathimport-path-identifierimport-path-identifier ­. import-path
import-path-identifieridentifieroperator



­定数の宣言



定数の宣言 はプログラムに、名前の付いた定数値を導入します。定数の宣言は、let キーワードを使用して宣言され、以下の形式です。


let : =



定数の宣言では、定数の名前 とイニシャライザ の値との間の結合を不変と定義し、定数の値が設定された後は、変更できません。つまり、定数がクラスオブジェクトで初期化されている場合、オブジェクト自体は変更できますが、定数の名前とそれが参照するオブジェクトとの間の結合は変更できません。


定数がグローバルのスコープで宣言される場合、一つの値で初期化されなければなりません。定数の宣言が関数またはメソッドの文脈で発生すると、その値が最初に読み取られる前に値が設定されていることが保証されている限り、後で初期化することができます。コンパイラが定数の値は決して読み取られないことを証明できる場合、定数に値を設定する必要はまったくありません。定数の宣言がクラスまたは構造体の宣言の文脈で発生する場合、それは 定数プロパティ とみなされます。定数の宣言は計算されたプロパティではないため、ゲッタやセッタはありません。


定数の宣言の 定数の名前 がタプルのパターンの場合、タプルの各項目の名前は、イニシャライザ の対応する値に結合されます。


let (firstNumber, secondNumber) = (10, 42)



この例では、firstNumber は値 10 の名前の付いた定数で、secondNumber は値 42 の名前の付いた定数です。いずれの定数も今は独立して使用できます。


  1. print("The first number is \(firstNumber).")
  2. // prints "The first number is 10."
  3. print("The second number is \(secondNumber).")
  4. // prints "The second number is 42."


型注釈 (:type) は、型の推測 で説明したように、定数名 の型が推測できる時、定数の宣言ではオプションです。


定数型プロパティを宣言するには、static 宣言修飾子で宣言をマークして下さい。クラスの定数型プロパティは、常に暗黙的に final です。サブクラスによるオーバーライドを許可または禁止する class または final 宣言修飾子でマークすることはできません。型プロパティは、型プロパティ で説明されています。


定数についての詳細とそれらを使用する場合のガイダンスは、 定数と変数 及び 格納されたプロパティ を参照して下さい。


定数の宣言の文法

constant-declarationattributes ­opt declaration-modifiers ­opt ­let ­pattern-initializer-list

pattern-initializer-listpattern-initializer | pattern-initializer ­, ­pattern-initializer-list
pattern-initializerpattern initializer ­opt
­ initializer= ­expression



­

変数の宣言



変数の宣言 は、プログラムに、名前の付いた変数値を導入し、var キーワードを使用して宣言されます。


変数の宣言には、いくつかの形式があり、名前の付いた、変更可能な値、格納された、計算された変数やプロパティ、格納された変数とプロパティ監視者、および静的変数プロパティを含む、様々な種類を宣言します。使用に適した形式は、変数が宣言されたスコープと、宣言しようとする変数の種類に依存します。


注意: プロトコルプロパティ宣言 で説明したように、プロトコル宣言の文脈でプロパティを宣言することもできます。


オーバーライド(上書き) で説明したように、override 宣言修飾子で、サブクラスのプロパティ宣言をマークし、サブクラスのプロパティをオーバーライドできます。



格納された変数と格納された変数のプロパティ



以下の形式で、格納された変数と格納された変数のプロパティを宣言します。


var : =



グローバルなスコープで変数の宣言のこの形式を定義し、関数のローカルなスコープや、クラスまたは構造体の宣言の文脈で定義して下さい。この形式で変数の宣言がグローバルなスコープまたは関数のローカルなスコープで宣言されると、それは 格納された変数 として参照されます。それがクラスまたは構造体の宣言の文脈の中で宣言された場合には、格納された変数のプロパティ として参照されます。


イニシャライザ はプロトコル宣言には存在できませんが、他のすべての文脈では、イニシャライザ はオプションです。つまり、イニシャライザ が存在しない場合、変数の宣言は、明示的な型注釈 (: type) を含めなければなりません。


定数の宣言と同じように、変数名 がタプルパターンであれば、タプルの各項目の名前は、イニシャライザ の対応する値に結合されます。


それらの名前が示唆するように、格納された変数または格納された変数プロパティの値は、メモリに格納されます。



計算された変数と計算されたプロパティ



以下の形式で計算された変数または計算されたプロパティを宣言します。


var : {
        get {
               
        }
        set() {
               
        }
}



グローバルなスコープでこの形式での変数の宣言を定義し、関数のローカルなスコープや、クラス、構造体、列挙型、または拡張機能の宣言の文脈で定義して下さい。この形式での変数の宣言がグローバルなスコープまたは関数のローカルなスコープで宣言されている場合、それは 計算された変数 として参照されます。クラス、構造体、または拡張機能の宣言の文脈内で宣言された場合には、計算されたプロパティ として参照されます。


ゲッタは、値を読み出すために使用され、セッタは、値を書き込むために使用されます。セッタ節はオプションであり、ゲッタのみが必要ならば、両方の節を省略でき、読み取り専用の計算されたプロパティ で説明したように、直接、要求された値を単に返す事ができます。しかし、セッタ節を提供するならば、ゲッタ節も提供しなければなりません。


セッタの名前 と、取り囲む括弧はオプションです。セッタの名前を提供する場合は、セッタへのパラメータ名として使用されます。セッタの名前を提供しない場合は、セッタ宣言の省略形 で説明したように、セッタへのデフォルトのパラメータ名は newValue です。


格納された名前付きの値や格納された変数プロパティとは異なり、計算された名前付きの値や、計算されたプロパティの値は、メモリに格納されません。


計算されたプロパティの詳細と例を見るには、計算されたプロパティ を参照してください。



格納された変数監視者とプロパティ監視者



willSetdidSet 監視者で、また、格納された変数またはプロパティをも宣言できます。監視者 (observer) で宣言された格納された変数やプロパティは、以下の形式です。


var : = {
        willSet() {
               
        }
        didSet() {
               
        }
}



グローバルなスコープで変数の宣言をこの形式で定義し、関数のローカルなスコープで定義するか、クラスまたは構造体の宣言の文脈で定義して下さい。この形式の変数の宣言がグローバルなスコープまたは関数のローカルなスコープで宣言された場合、監視者は、格納された変数の監視者 として参照されます。クラスまたは構造体の宣言の文脈の中で宣言された場合、監視者は、プロパティの監視者 として参照されます。


全ての格納されたプロパティに、プロパティの監視者を追加できます。また、プロパティ監視者のオーバーライド で説明したように、サブクラス内のプロパティをオーバーライドすることで (格納されたまたは計算された) 全てのの継承されたプロパティにも、プロパティ監視者を追加できます。


イニシャライザ は、クラスまたは構造体の宣言の文脈ではオプションですが、他の場所ではどこでも必須です。 注釈は、型がイニシャライザ から推測可能であればオプションです。この式は、プロパティの値を初めて読み取るときに評価されます。プロパティの初期値を読み取らずに上書きすると、この式は、プロパティに初めて書き込む前に評価されます。


willSetdidSet 監視者は、変数またはプロパティの値が設定されているときに監視する (かつ適切に対応する) 方法を提供します。変数またはプロパティが最初に初期化されるとき、監視者は呼び出されません。代わりに、それらは値が初期化文脈の外側で設定された時にのみ呼び出されます。


willSet 監視者は、変数またはプロパティの値が設定される直前に呼び出されます。新しい値は定数として willSet 監視者に渡されるので、それは willSet 節の実装中には変更できません。didSet 監視者は新しい値が設定された直後に呼び出されます。willSet 監視者とは対照的に、変数またはプロパティの古い値は、まだそれにアクセスする必要がある場合に didSet 監視者に渡されます。つまり、自身の didSet 監視者節内の変数またはプロパティに値を代入する場合、代入した新しい値が、ちょうど設定された値を置き換え、willSet 監視者に渡されます。


­

セッタの名前willSetdidSet 節内を囲むカッコはオプションです。セッタの名前を提供する場合、それらは willSetdidSet 監視者へのパラメータ名として使用されます。セッタの名前を提供しない場合、willSet 監視者に対するデフォルトのパラメータ名は newValue になり、didSet 監視者へのデフォルトのパラメータ名は oldValue になります。


willSet 節を提供する際には didSet 節はオプションです。同様に、 didSet 節を提供する際には、willSet 句はオプションです。


didSet 監視者の本体が古い値を参照している場合、古い値を使用可能にするために、監視者の前にゲッタが呼び出されます。それ以外の場合、新しい値はスーパークラスのゲッタを呼び出さずに保存されます。以下の例は、スーパークラスによって定義され、監視者を追加するためにそのサブクラスによってオーバーライドされる計算されたプロパティを示しています。


  1. class Superclass {
  2. private var xValue = 12
  3. var x: Int {
  4. get { print("Getter was called"/); return xValue }
  5. set { print("Setter was called"); xValue = newValue }
  6. }
  7. }
  8. // This subclass doesn't refer to oldValue in its observer, so the
  9. // superclass's getter is called only once to print the value.
  10. class New: Superclass {
  11. override var x: Int {
  12. didSet { print("New value \(x)") }
  13. }
  14. }
  15. let new = New()
  16. new.x = 100
  17. // Prints "Setter was called"
  18. // Prints "Getter was called"
  19. // Prints "New value 100"
  20. // This subclass refers to oldValue in its observer, so the superclass's
  21. // getter is called once before the setter, and again to print the value.
  22. class NewAndOld: Superclass {
  23. override var x: Int {
  24. didSet { print("Old value \(oldValue) - new value \(x)") }
  25. }
  26. }
  27. let newAndOld = NewAndOld()
  28. newAndOld.x = 200
  29. // Prints "Getter was called"
  30. // Prints "Setter was called"
  31. // Prints "Getter was called"
  32. // Prints "Old value 12 - new value 200"


詳細とプロパティ監視者を使用する方法の例については、プロパティ監視者 を参照してください。



型変数プロパティ



型変数プロパティを宣言するには、static 宣言修飾子で宣言をマークして下さい。サブクラスがスーパークラスの実装をオーバーライドするのを許す代わりに、クラスは型の計算されたプロパティを class 宣言修飾子でマークできます。型プロパティは、型プロパティ で議論しました。


変数宣言の文法

variable-declarationvariable-declaration-head ­pattern-initializer-list
variable-declarationvariable-declaration-head ­variable-name ­type-annotation ­code-block
variable-declarationvariable-declaration-head ­­variable-name ­type-annotation getter-setter-block
variable-declarationvariable-declaration-head ­­variable-name ­type-annotation ­getter-setter-keyword-block
variable-declarationvariable-declaration-head ­­variable-name initializer willSet-didSet-block
variable-declarationvariable-declaration-head ­variable-name ­type-annotation initializer ­opt >willSet-didSet-block

variable-declaration-headattributes ­opt declaration-modifiers ­opt ­var
variable-nameidentifier

getter-setter-block­code-bloc
getter-setter-block{ ­getter-clause ­setter-clause ­opt ­}
getter-setter-block{ setter-clause ­getter-clause ­}
­ getter-clauseattributes ­opt mutation-modifier ­opt ­get code-block
setter-clauseattributes ­opt mutation-modifier ­­­opt ­set setter-name opt ­code-block­
setter-name → ( identifier ­)

getter-setter-keyword-block{ ­getter-keyword-clause­ setter-keyword-clause opt ­}
getter-setter-keyword-block{ setter-keyword-clause ­getter-keyword-clause ­}
getter-keyword-clauseattributes opt mutation-modifier ­­­opt ­get
setter-keyword-clauseattributes ­opt mutation-modifier ­­­opt ­set

willSet-didSet-block{ ­willSet-clause ­didSet-clause ­opt ­}
willSet-didSet-block{ ­didSet-clause ­willSet-clause ­opt ­}
willSet-clauseattributes ­opt willSet ­setter-name ­opt ­code-block­
didSet-clauseattributes ­opt ­didSet setter-name ­opt ­code-block



型エイリアス宣言



型エイリアス宣言 は、プログラムに既存の型の、名前のついたエイリアスを導入します。型エイリアス宣言は、キーワード typealias を使用し、以下のような形式で宣言します:


typealias =



型エイリアスが宣言された後は、エイリアスの 名前 はプログラムのどこでも 既存の型 の代わりに使用できます。既存の型 は、名前付きの型または複合の型にできます。型エイリアスは、新しい型を作成することはありません。それは単に既存の型を名前で参照することを許可するだけです。


型エイリアス宣言は、汎用パラメータを使用して既存の汎用型に名前を付けることができます。型エイリアスは、既存の型の汎用パラメータの一部またはすべてに具体的な型を提供できます。例えば:


  1. typealias StringDictionary<Value> = Dictionary<String, Value>
  2. // The following dictionaries have the same type.
  3. var dictionary1: StringDictionary<Int> = [:]
  4. var dictionary2: Dictionary<String, Int> = [:]


型エイリアスが汎用パラメータで宣言されている場合、それらのパラメータの制約は、既存の型の汎用パラメータの制約と正確に一致しなければなりません。例えば:


typealias DictionaryOfInts<Key: Hashable> = Dictionary<Key, Int>



型エイリアスと既存の型は同じ意味で使用できるため、型エイリアスは追加の汎用制約を導入できません。


型エイリアスは、宣言からすべての汎用パラメータを省略して、既存の型の汎用パラメータを転送できます。たとえば、ここで宣言されている Diccionario の型エイリアスは、Dictionary と同じ汎用パラメータと制約を持ちます。


typealias Diccionario = Dictionary


プロトコル宣言の中で、型エイリアスは、頻繁に使用される型に、短くてもっと便利な名前を付けることができます。例えば:


  1. protocol Sequence {
  2. associatedtype Iterator: IteratorProtocol
  3. typealias Element = Iterator.Element
  4. }
  5. func sum<T: Sequence>(_ sequence: T) -> Int where T.Element == Int {
  6.         // ...
  7. }


この型エイリアスがなければ、sum 関数は関連する型を T.Element の代わりに T.Iterator.Element として参照しなければならないでしょう。


プロトコルに関連した型の宣言 も参照してください。



型エイリアス宣言の文法

typealias-declarationattributes opt access-level-modifier opt ­typealias­ typealias-name ­generic-parameter-clause ­opt typealias-assignment
­ typealias-nameidentifier
typealias-assignment= ­type­



関数の宣言


関数の宣言 は、プログラムに関数やメソッドを導入します。クラス、構造体、列挙型、またはプロトコルの文脈で宣言された関数は、メソッド として参照されます。関数の宣言は、キーワード func を使用して宣言し、以下のような形式を持っています:


func ( ) -> {
       
}



関数が Void の戻り値の型を持っている場合、以下のように、戻り値の型を省略できます:


func ( ) {
       
}



各パラメータの型は含まれなければならないーそれは推測できません。パラメータの型の前に inout を書き込むと、関数のスコープ内でそのパラメータを変更できます。in-out パラメータについては、以下の In-Out パラメータ で詳しく議論しています。


その に単一の式のみが含まれる関数の宣言は、その式の値を返すと理解されます。この暗黙の戻り値の構文は、式の型と関数の戻り値の型が Void ではなく、何も case のない Never のような列挙型でない場合にのみ考慮されます。


関数は、関数の戻り値の型としてタプル型を使用して複数の値を返すことができます。


関数の定義は、別の関数の宣言内に表示できます。このような関数は、入れ子になった関数 として知られています。


入れ子になった関数は、決してエスケープしないことが保証されている値 (in-out パラメータなど) をキャプチャしている場合、またはエスケープしていない関数の引数として渡された場合はエスケープしません。それ以外の場合は、入れ子になった関数はエスケープする関数です。


入れ子になった関数の詳細については、入れ子になった関数 を参照してください。



パラメータ名


関数のパラメータは、各パラメータがいくつかの形式のいずれか1つを持っている、カンマ区切りのリストです。関数呼び出しの引数の順序は、関数の宣言内のパラメータの順序と一致しなければなりません。パラメータリストの最も簡単なエントリの形式は以下のとおりです。


:



パラメータには関数本体内で使用される名前と、関数またはメソッドを呼び出すときに使用される引数のラベルがあります。デフォルトでは、パラメータ名も引数ラベルとして使用されます。例えば:


  1. func f(x: Int, y: Int) -> Int { return x + y }
  2. f(x: 1, y: 2) // both x and y are labeled


引数ラベルのデフォルトの動作は、以下のいずれか 1 つの形式で上書き(オーバーライド)できます。


:
_ :


パラメータ名の前の名前は、パラメータに明示的な引数ラベルを与え、これはパラメータ名とは異なる場合があります。対応する引数は、関数またはメソッドの呼び出しで与えられた引数ラベルを使用しなければなりません。


パラメータ名の前のアンダースコア (_ ) は、引数のラベルを抑制します。対応する引数は、関数またはメソッドの呼び出しでラベルを持ってはなりません。


  1. func repeatGreeting(_ greeting: String, count n: Int) { /* Greet n times */ }
  2. repeatGreeting("Hello, world!", count: 2) // count is labeled, greeting is not


In-Out パラメータ


In-Out パラメータは、以下のように渡されます。


  1. 関数が呼び出されると、引数の値がコピーされます。
  2. 関数の本体では、コピーが変更されます。
  3. 関数が戻ると、コピーの値が元の引数に代入されます。

この動作は、コピーインコピーアウト または 値の結果による呼び出し と呼ばれます。たとえば、計算されたプロパティまたは監視者を持つプロパティが in-out パラメータとして渡されると、そのゲッタは関数呼び出しの一部として呼び出され、そのセッタは関数の戻り値の一部として呼び出されます。


最適化として、引数がメモリ内の物理アドレスに格納された値である場合、関数本体の内部と外部の両方で同じメモリ位置が使用されます。最適化された動作は、参照による呼び出し として知られます。コピーするオーバヘッドを除去しながら、コピーインコピーアウトモデルのすべての要件をこれは満たします。最適化の有無にかかわらず、正しく動作するように、参照渡し呼び出しの最適化に依存せずに、コピーインコピーアウトによって与えられたモデルを使用してコードを記述して下さい。


元の値が現在のスコープで使用可能であったとしても、in-out 引数として渡された値には関数内ではアクセスしないでください。元の値へのアクセスは値の同時アクセスであり、これは Swift のメモリ排他性保証に違反します。同じ理由で、複数の in-out パラメータに同じ値を渡すことはできません。


メモリの安全性とメモリの排他性の詳細については、メモリの安全性 を参照してください。


in-out パラメータをキャプチャするクロージャまたは入れ子にされた関数は、エスケープしてはいけません。in-out パラメータを変更せずにキャプチャする必要がある場合や、他のコードによる変更を監視する必要がある場合は、キャプチャリストを使用して明示的にパラメータを変更せずにキャプチャします。


  1. func someFunction(a: inout Int) -> () -> Int {
  2. return { [a] in return a + 1 }
  3. }


in-out パラメータをキャプチャして変更する必要がある場合は、関数が返す前にすべての変異が完了していることを保証するマルチスレッドのコードのように、明示的なローカルコピーを使用します。


  1. func multithreadedFunction(queue: DispatchQueue, x: inout Int) {
  2. // Make a local copy and manually copy it back.
  3. var localX = x
  4. defer { x = localX }
  5. // Operate on localX asynchronously, then wait before returning.
  6. queue.async { someMutatingOperation(&localX) }
  7. queue.sync {}
  8. }


in-out パラメータの詳細と例については、In-Out パラメータ を参照してください。



パラメータの特殊な種類


パラメータは無視することができ、可変個の値を取り、デフォルト値を提供し、以下の形式を使用します:


_ :
: ...
: =



アンダースコア (_ ) パラメータは、明示的に無視され、関数の本体内ではアクセスできません。


基本型の名前のパラメータの直後に続く3つのドット (... ) は、可変個引数パラメータとして理解されます。関数は、最大1つの可変個パラメータを持つ事ができます。可変個のパラメータは、基本型名の要素を含む配列として扱われます。例えば、可変個のパラメータ Int...[Int] として扱われます。可変個のパラメータを使用する例については、可変個パラメータ を参照してください。


等号 (=) を伴ったパラメータと、その型の後の式は、与えられた式のデフォルト値を持っていると理解されます。関数が呼び出されたときに、与えられた式は評価されます。関数を呼び出すときにパラメータを省略すると、デフォルト値が代わりに使用されます。



  1. func f(x: Int = 42) -> Int { return x }
  2. f()                // Valid, uses default value
  3. f(x: 7)          // Valid, name and value provided
  4. f(7)              // Invalid, value provided without its name


メソッドの特殊な種類


self を変更する、列挙型または構造体上のメソッドは mutating 宣言修飾子でマークされなければなりません。


スーパークラスのメソッドをオーバーライドするメソッドは、override 宣言修飾子でマークされなければなりません。override 修飾子なしでメソッドをオーバーライドするか、スーパークラス・メソッドをオーバーライドしないメソッドで override 修飾子を使用すると、コンパイル時エラーになります。


型のインスタンスではなく、型に関連したメソッドは、列挙型と構造体では static 宣言修飾子、またはクラスでは static または class 宣言修飾子でマークされなければなりません。class 宣言修飾子でマークされたクラス型メソッドは、サブクラスの実装によってオーバーライドできます。class final または static とマークされたクラス型メソッドはオーバーライドできません。


特別な名前のメソッド


特別な名前を持ついくつかのメソッドは、関数呼び出し構文のシンタックスシュガーを有効にします。型がこれらのメソッドの 1 つを定義する場合、その型のインスタンスは関数呼び出し構文で使用できます。関数呼び出しは、そのインスタンスで特別に名前が付けられたメソッドの 1 つへの呼び出しであると理解されます。


クラス、構造体、または列挙型は、dynamicCallable で説明した dynamicCall(withArguments:) メソッドまたは dynamicCall(withKeywordArguments:) メソッドを定義するか、下記のように call-as-function (関数として呼び出す) メソッドを定義することにより、関数呼び出し構文をサポートできます。型が関数として呼び出すメソッドと dynamicCallable 属性で使用されるメソッドの一つの両方を定義している場合、コンパイラはどちらかのメソッドを使用できる状況で関数として呼び出すメソッドを優先します。


call-as-function (関数として呼び出す) メソッドの名前は callAsFunction()、または callAsFunction( で始まり、ラベル付きまたはラベルなしの引数を追加する別の名前です。たとえば、callAsFunction(_:_:) および callAsFunction(something:) も有効な call-as-function (関数として呼び出す) メソッドの名前です。


次の関数呼び出しは同等です。


  1. struct CallableStruct {
  2. var value: Int
  3. func callAsFunction(_ number: Int, scale: Int) {
  4. print(scale * (number + value))
  5. }
  6. }
  7. let callable = CallableStruct(value: 100)
  8. callable(4, scale: 2)
  9. callable.callAsFunction(4, scale: 2)
  10. // Both function calls print 208.


call-as-function (関数として呼び出す) メソッドと dynamicCallable 属性からのメソッドは、型システムにコード化する情報量と実行時に可能な動的動作の量との間で異なるトレードオフを行います。call-as-function (関数として呼び出す) メソッドを宣言するときは、引数の数と各引数の型とラベルを指定します。dynamicCallable 属性のメソッドは、引数の配列を保持するために使用される型のみを指定します。


call-as-function (関数として呼び出す) メソッド、または dynamicCallable 属性からのメソッドを定義すると、その型のインスタンスを、関数呼び出し式以外の文脈の関数であるかのように使用することはできません。例えば:


  1. let someFunction1: (Int, Int) -> Void = callable(_:scale:)   // Error
  2. let someFunction2: (Int, Int) -> Void = callable.callAsFunction(_:scale:)


subscript(dynamicMemberLookup:) サブスクリプトを使用すると、dynamicMemberLookup で説明したように、メンバー検索のシンタックスシュガーが有効になります。


Throw する関数とメソッド


エラーを throw できる関数とメソッドは、throws キーワードでマークされなければなりません。これらの関数とメソッドは、throw する関数throw するメソッド として知られています。これらは以下の形式です:


func ( ) throws -> {
       
}



throw する関数またはメソッドへの呼び出しは、try または try! 式で包み込まなければなりません (つまり、try または try! 演算子のスコープ内にあります)。


throws キーワードは関数の型の一部であり、throw しない関数は throw する関数のサブタイプです。その結果、throw する関数と同じ場所で throw しない関数を使用できます。


関数がエラーを throw できるかどうかだけに基づいて関数をオーバーロードすることはできません。つまり、関数の パラメータ がエラーを throw できるかどうかに基づいて、関数をオーバーロードできます。


throw するメソッドは throw しないメソッドをオーバーライドできず、また throw するメソッドは throw しないメソッドのプロトコル要件を満たすことができません。つまり、throw しないメソッドは throw するメソッドをオーバーライドでき、throw しないメソッドは throw するメソッドのプロトコル要件を満たすことができます。



Rethrow する関数とメソッド


rethrows キーワードで関数またはメソッドを宣言すると、その関数のパラメータの1つがエラーを throw する場合にのみエラーを throw することを示すことができます。これらの関数とメソッドは、rethrow する関数rethrow するメソッド として知られています。rethrow する関数とメソッドは、少なくとも1つの throw する関数パラメータを持っていなければなりません。


  1. func someFunction(callback: () throws -> Void ) rethrows {
  2. try callback()
  3. }


rethrow する関数またはメソッドには、catch 節の中にのみ throw 文を含めることができます。これにより、 do-catch 文内で throw する関数を呼び出し、異なるエラーを throw する事により catch 節内のエラーを処理できます。さらに、catch 節は、rethrow する関数の throw するパラメータの1つによって throw されたエラーのみを処理しなければなりません。たとえば、catch 節が alwaysThrows() によって throw されたエラーを処理するため、以下の例は無効です。


  1. func alwaysThrows() throws {
  2. throw SomeError.error
  3. }
  4. func someFunction(callback: () throws -> Void) rethrows {
  5. do {
  6. try callback()
  7. try alwaysThrows()    // Invalid, alwaysThrows() isn't a throwing parameter
  8. } catch {
  9. throw AnotherError.error
  10. }
  11. }


throw するメソッドは rethrow するメソッドをオーバーライドできませんし、throw するメソッドは rethrow するメソッドのプロトコル要件を満たすことができません。つまり、rethrow するメソッドは throw するメソッドをオーバーライドでき、rethrow するメソッドは throw するメソッドのプロトコル要件を満たすことができます。


Never Return (返さない) 関数


Swift は、関数またはメソッドが呼び出し側に返さないことを示す Never 型を定義しています。Never の戻り値の型を持つ関数とメソッドは、返さない (nonreturning) と呼ばれます。返さない関数とメソッドは、回復不可能なエラーを引き起こすか、無限に続く一連の作業を開始するかのどちらかです。つまり、呼び出し直後に実行されるコードは決して実行されない事を意味します。throw と rethrow する関数は、それらが返さなかったとしても、プログラム制御を適切な catch ブロックに転送できます。


Guard 文 で説明したように、guard 文の else 節を終結させるために、返さない関数またはメソッドを呼び出すことができます。


返さないメソッドをオーバーライドすることはできますが、新しいメソッドはその戻り値の型と返さない動作を保持しなければなりません。


関数の宣言の文法

function-declarationfunction-head ­function-name generic-parameter-clause ­opt function-signature generic-where-clause ­opt function-body

function-headattributes ­opt declaration-modifiers ­opt ­func
function-nameidentifieroperator
­
function-signatureparameter-clause throws ­opt function-result ­opt
function-signatureparameter-clause rethrows ­function-result ­opt
function-result-> attributes ­opt type­
function-bodycode-block­

parameter-clause(­ ) parameter-list ­
parameter-listparameterparameter ­, ­parameter-list
parameterexternal-parameter-name ­opt ­local-parameter-name type-annotation­ default-argument-clause ­opt
parameter­external-parameter-name ­opt ­local-parameter-name type-annotation­
parameterexternal-parameter-name ­opt ­local-parameter-name type-annotation­ . . .
external-parameter-nameidentifier
local-parameter-nameidentifier
­ default-argument-clause → =­ expression­



列挙型の宣言


列挙型の宣言 は、プログラムに名前の付いた列挙型を導入します。


列挙型の宣言には、2つの基本的な形式があり、enum キーワードを使用して宣言されます。列挙型の本体は、ゼロ個以上の値ー列挙型の case と呼ばれます–を含む形式と、以下のいずれかの形式で宣言されます:計算されたプロパティ、インスタンス・メソッド、型メソッド、イニシャライザ、型エイリアス、さらには他の列挙型、構造体、およびクラスの宣言を含む、宣言の全てが含まれています。列挙型の宣言は、デイニシャライザまたはプロトコル宣言を含めることはできません。


列挙型は、プロトコルをいくらでも採用できますが、クラス、構造体、または他の列挙体からは継承できません。


クラスや構造体とは異なり、列挙型には、暗黙的に提供されるデフォルトのイニシャライザはありません。すべてのイニシャライザは、明示的に宣言しなければなりません。イニシャライザは、列挙型内の他のイニシャライザにデリゲートできますが、初期化プロセスは、self に列挙型の case の一つをイニシャライザが代入した後にのみ、完了します。


構造体のように、しかしクラスとは異なり、列挙型は、値型です。変数や定数に代入されたとき、または関数呼び出しで引数として渡されたとき、列挙型のインスタンスはコピーされます。値型の詳細については、構造体と列挙型は値型 を参照してください。


拡張機能の宣言 で議論したように、拡張機能の宣言で列挙型の動作を拡張できます。



任意の型の case を列挙


以下の形式で、任意の型の列挙型の case を含む列挙型を宣言できます。


enum : {
        case
        case ( )
}



この形式で宣言された列挙型は時々、他のプログラミング言語では 差別された共用体 (discriminated unions) と呼ばれています。


この形式では、それぞれの case ブロックは、case キーワードに引き続き、カンマで区切られた1つ以上の列挙型の case で構成されます。各 case の名前は固有でなければなりません。各 case はまた、与えられた型の値を格納するように指定できます。これらの型は、直後に case の名前が続く、関連した値の型 のタプルで指定されています。


関連した値を格納する列挙型の case は、指定された関連した値を持つ列挙型のインスタンスを作成する関数として使用できます。関数と同様に、列挙型 case への参照を取得し、後でコードに適用できます。


  1. enum Number {
  2. case integer(Int)
  3. case real(Double)
  4. }
  5. let f = Number.integer
  6. // f is a function of type (Int) -> Number
  7. // Apply f to create an array of Number instances with integer values
  8. let evenInts: [Number] = [0, 2, 4, 6].map(f)


詳細および関連した値型の case の例に関しては、関連する値 を参照してください。



間接による列挙


列挙型は再帰的構造体を持つことができます。つまり、列挙型自体のインスタンスである関連した値を持つ case を持つことができます。しかし、列挙型のインスタンスには値の意味があります。つまり、メモリ内に固定したレイアウトがあることを意味します。再帰をサポートするために、コンパイラは間接のレイヤを挿入しなければなりません。


特定の列挙型の case の間接化を有効にするには、それを indirect 宣言修飾子でマークします。indirect (間接の) case は関連する値を持たなければなりません。


  1. enum Tree<T> {
  2. case empty
  3. indirect case node(value: T, left: Tree, right: Tree)
  4. }


関連する値を持つ列挙型の全ての case で間接を有効にするには、列挙型全体を indirect 修飾子でマークして下さい。これは、列挙型が各々を indirect 修飾子でマークする必要がある case が多数ある場合に便利です。


indirect 修飾子でマークされた列挙型は、関連する値を持つ case とそうでない case が混在することがあります。それは、indirect 修飾子でもマークされている case を含むことはできないと言う事です。


生の値型の case を列挙


以下の形式で、同じ基本型の列挙型の case を含む列挙型を宣言できます。


enum : , {
        case =
        case =
}



この形式では、それぞれの case ブロックは case キーワードで構成され、カンマで区切られた1つ以上の列挙型の case が続きます。最初の形式での case とは異なり、それぞれの case は、同じ基本型の 生の値 と呼ばれる基本的な値を持っています。これらの値の型は 生の値型 で指定されており、整数、浮動小数点数、文字列、または一つの文字を表さなければなりません。具体的には、生の値型Equatable プロトコルと以下のプロトコルのいずれか1つに準拠しなければなりません:整数リテラル用の ExpressibleByIntegerLiteral、浮動小数点リテラル用の ExpressibleByFloatLiteral、任意の文字数を含む文字列リテラル用の ExpressibleByStringLiteral、唯一つの文字を含む文字列リテラル用の ExpressibleByUnicodeScalarLiteral または ExpressibleByExtendedGraphemeClusterLiteral です。それぞれの case には固有の名前があり、固有の生の値が割り当てられていなければなりません。


生の値型が Int として指定されており、明示的に case に値を割り当てていない場合は、暗黙的に 0,1,2, などの値が割り当てられます。Int 型の割り当てていない各 case には、前の case の生の値から自動的にインクリメント (増分) された生の値が暗黙的に割り当てられます。


  1. enum ExampleEnum: Int {
  2. case a, b, c = 5, d
  3. }


上記の例では、ExampleEnum.a の生の値は 0 で、ExampleEnum.b の値は 1 です。ExampleEnum.c の値が明示的に 5 に設定されているため、ExampleEnum.d の値は自動的に 5 から増分され、したがって、6 です。


生の値型が String として指定されており、明示的に値を case に割り当てていない場合、割り当てられていない各 case は、その case の名前と同じテキストの文字列が暗黙的に割り当てられます。


  1. enum GamePlayMode: String {
  2. case cooperative, individual, competitive
  3. }


上記の例では、GamePlayMode.cooperative の生の値は "cooperative" で、GamePlayMode.individual の生の値は "individual" で、GamePlayMode.competitive の生の値は "competitive" です。


生の値型の case のある列挙型は、Swift 標準ライブラリで定義されている RawRepresentable プロトコルに暗黙的に準拠しています。結果として、それらは rawValue プロパティを持ち、init?(rawValue: RawValue) の署名で、失敗可能なイニシャライザを持っています。ExampleEnum.b.rawValue のように、列挙型 case の生の値にアクセスするには rawValue プロパティを使用できます。optional の case を返す ExampleEnum(rawValue: 5) のように、それが一つであれば、列挙型の失敗可能なイニシャライザを呼び出すことによって、対応する case を見つけて生の値を使用することもできます。詳細について、及び生の値型を持つ case の例は、生の値 を参照してください。


列挙型 case へのアクセス


列挙型の case を参照するには、EnumerationType.enumerationCase のように、ドット (.) 構文を使用します。列挙型が文脈から推測できるときには、列挙型の構文 および 暗黙のメンバ式 で説明したように、(ドットはまだ必要ですが)それを省略できます。


switch 文で列挙型の値の一致 で示したように、列挙型の case の値を確認するには、switch 文を使って下さい。列挙型 case のパターン で説明したように、列挙型は switch 文の case ブロックで列挙型 case パターンに対してパターン照合されます。



列挙型の宣言の文法

enum-declarationattributes ­opt access-level-modifier ­opt union-style-enum­
enum-declarationattributes opt­ access-level-modifier ­opt raw-value-style-enum

union-style-enumindirect opt enum ­enum-name generic-parameter-clause opt type-inheritance-clause ­opt generic-where-clause opt { ­union-style-enum-members­ opt ­}
union-style-enum-membersunion-style-enum-member union-style-enum-members ­opt
union-style-enum-memberdeclarationunion-style-enum-case-clause | compiler-control-statement
union-style-enum-case-clauseattributes ­opt indirect opt ­case union-style-enum-case-list
union-style-enum-case-listunion-style-enum-caseunion-style-enum-case ­, union-style-enum-case-list
union-style-enum-caseenum-case-name­ tuple-type opt
enum-nameidentifier
enum-case-nameidentifier

raw-value-style-enumenum ­enum-name generic-parameter-clause ­opt type-inheritance-clause ­generic-where-clause opt {­ raw-value-style-enum-members ­}
­ raw-value-style-enum-membersraw-value-style-enum-member raw-value-style-enum-members ­opt
raw-value-style-enum-memberdeclaration­ | raw-value-style-enum-case-clause | compiler-control-statement
raw-value-style-enum-case-clauseattributes ­opt ­case ­raw-value-style-enum-case-list
raw-value-style-enum-case-listraw-value-style-enum-case ­| raw-value-style-enum-case ­, ­raw-value-style-enum-case-list
raw-value-style-enum-caseenum-case-name raw-value-assignment ­opt
raw-value-assignment= raw-value-literal
raw-value-literalnumeric-literalstatic-string-literalboolean-literal


構造体の宣言


構造体の宣言 は、プログラムに名前の付いた構造体の型を導入します。構造体の宣言は、struct キーワードを使用して宣言し、以下のような形式です:


struct : {
       
}



構造体の本体は、ゼロ個以上の 宣言 を含んでいます。これらの 宣言 は、格納されたプロパティと計算されたプロパティの両方、型プロパティ、インスタンスメソッド、型メソッド、イニシャライザ、サブスクリプト、型エイリアス、さらには他の構造体、クラス、および列挙型の宣言を含めることができます。構造体の宣言は、デイニシャライザまたはプロトコルの宣言を含めることはできません。議論と宣言の様々な種類を含む構造体のいくつかの例については、構造体とクラス を参照してください。


構造体型は、プロトコルをいくつでも採用することができますが、クラス、列挙型、または他の構造体から継承することはできません。


以前に宣言された構造体のインスタンスを作成するには3つの方法があります。


構造体の宣言されたプロパティの初期化プロセスは、 初期化 で説明しました。


プロパティにアクセス で説明したように、構造体インスタンスのプロパティは、ドット (.) 構文を使用してアクセスできます。


構造体は値型であり、変数や定数に代入されたとき、または関数呼び出しに引数として渡されたときには構造体のインスタンスはコピーされます。値型の詳細については、構造体と列挙型は値型 を参照してください。


拡張機能の宣言 で議論したように、拡張機能の宣言で構造体型の動作を拡張できます。



構造体の宣言の文法

struct-declarationattributes ­opt access-level-modifier ­opt ­struct ­struct-name­ generic-parameter-clause ­opt ­type-inheritance-clause ­opt generic-where-clause ­opt ­struct-body
struct-nameidentifier
struct-body struct-members opt ­}

struct-membersstruct-member struct-members ­opt
struct-memberdeclarations­ | compiler-control-statement



クラスの宣言


クラスの宣言 は、プログラムに名前の付いたクラス型を導入します。クラスの宣言は、class キーワードを使用して宣言し、以下のような形式です:


class : , {
       
}



クラスの本体は、ゼロ個以上の 宣言 を含んでいます。これらの 宣言 は、格納されたプロパティ、計算されたプロパティの両方、インスタンスメソッド、型メソッド、イニシャライザ、一つのデイニシャライザ、サブスクリプト、型エイリアス、さらには他のクラス、構造体、および列挙型の宣言を含めることができます。クラスの宣言は、プロトコルの宣言を含めることはできません。議論や宣言の様々な種類を含むクラスのいくつかの例については、構造体とクラス を参照してください。


クラス型は、1つの親クラス、その スーパークラス からしか継承することができませんが、いくつでもプロトコルを採用できます。スーパークラス は、クラス名 とコロンに続いて最初に現れ、全ての 採用したプロトコル が続きます。汎用クラスは、他の汎用および非汎用クラスから継承できますが、非汎用クラスは、他の非汎用クラスからのみ継承できます。コロンの後に、汎用スーパークラスのクラス名を記述するときは、その汎用パラメータ句を含め、その汎用クラスのフルネームを含めなければなりません。


イニシャライザ宣言 で説明したように、クラスは指定イニシャライザと、コンビニエンス・イニシャライザを持てます。クラスの指定イニシャライザは、クラスの宣言されたすべてのプロパティを初期化しなければならず、そのスーパークラスの指定イニシャライザのいずれかを呼び出す前にそうしなければなりません。


クラスは、そのスーパークラスのプロパティ、メソッド、サブスクリプト、およびイニシャライザをオーバーライドできます。オーバーライドされたプロパティ、メソッド、サブスクリプト、および指定イニシャライザは override 宣言修飾子でマークされなければなりません。


サブクラスが、スーパークラスのイニシャライザを実装するように要求するには、required 宣言修飾子でスーパークラスのイニシャライザをマークして下さい。そのイニシャライザのサブクラスの実装も required 宣言修飾子でマークされなければなりません。


スーパークラス で宣言されたプロパティとメソッドは、現在のクラスによって継承されますが、スーパークラス 内で宣言された指定イニシャライザは、自動イニシャライザの継承 で説明した条件をサブクラスが満たす場合にのみ継承されます。Swift のクラスはユニバーサル基本クラスから継承しません。


以前に宣言されたクラスのインスタンスを作成するには2つの方法があります。


プロパティにアクセス で説明したようにドット (.) 構文でクラスインスタンスのプロパティにアクセスできます。


クラスは、参照型です。クラスのインスタンスは、変数や定数に代入されたとき、または関数呼び出しの引数として渡されたときには、コピーされるのではなく、参照されます。参照型については、構造体と列挙型は値型 を参照してください。


拡張機能の宣言 で議論したように、拡張機能の宣言でクラス型の動作を拡張することができます。



クラス宣言の文法

class-declarationattributes opt access-level-modifier ­opt final ­opt ­class class-name generic-parameter-clause ­opt type-inheritance-clause ­opt generic-where-clause ­opt ­class-body
class-declarationattributes opt final access-level-modifier ­opt ­class class-name generic-parameter-clause ­opt ­type-inheritance-clause ­opt generic-where-clause ­opt ­class-body
class-nameidentifier
class-body ­class-members ­opt ­}

class-membersclass-member ­class-members ­opt
­ class-memberdeclarations | compiler-control-statement
­


プロトコルの宣言


プロトコルの宣言 は、プログラムに名前の付いたプロトコル型を導入します。プロトコルの宣言は protocol キーワードを使用して global のスコープで宣言し、以下の形式です:


protocol : {
       
}



プロトコルの本体は、ゼロ個以上の プロトコル·メンバ宣言 を含み、プロトコルが満たさなければならない全ての型が採用している準拠要件を記述します。具体的には、プロトコルは、準拠する型が、特定のプロパティ、メソッド、イニシャライザ、およびサブスクリプトを実装しなければならないことを宣言できます。プロトコルはまた、プロトコルのさまざまな宣言間の関係を指定できる、関連する型 と呼ばれる型エイリアスの特別な種類も宣言できます。プロトコルメンバ宣言 は以下に詳細に説明します。


プロトコル型は、他のプロトコルからいくつでも継承できます。プロトコル型が他のプロトコルから継承した場合、それら他のプロトコルからの一連の要件は集約され、そして現在のプロトコルから継承する全ての型は、これらすべての要件に準拠しなければなりません。プロトコルの継承を使用する方法の例については、プロトコルの継承 を参照してください。


注意: プロトコル成分の型を使用して、複数のプロトコルの準拠要件を集約することもできます。詳しくは プロトコルを構成する型 と、プロトコルの構成 をご覧下さい。


その型の拡張機能の宣言でプロトコルを採用することにより、以前に宣言された型にプロトコル準拠を追加できます。拡張機能では、採用したプロトコル要件のすべてを実装しなければなりません。型がすでにすべての要件を実装している場合は、拡張機能の宣言の本体を空のまま残すことができます。


デフォルトでは、プロトコルに準拠する型は、プロトコルで宣言されたすべてのプロパティ、メソッド、およびサブスクリプトを実装しなければなりません。つまり、準拠する型によるそれらの実装はオプションであることを指定するには、optional の宣言修飾子でこれらのプロトコルメンバ宣言をマークできます。 optional の修飾子は、objc 属性でマークされているメンバにのみ適用でき、objc 属性でマークされたプロトコルメンバにのみ適用できます。その結果、クラス型だけが、optional メンバの要件を含むプロトコルに準拠し、採用できます。optional の宣言修飾子を使用する方法の詳細、また optional のプロトコルメンバにアクセスする方法ー例えば、準拠型がそれらを実装しているかどうかわからないときは、Optional のプロトコル要件 を参照してください。


列挙型の case は、型メンバのプロトコル要件を満たすことができます。具体的には、値が関連していない列挙型の case は、Self 型の取得専用の型変数のプロトコル要件を満たし、また値が関連している列挙型の case は、そのパラメータと引数ラベルが case の関連した値と一致する Self を返す関数のプロトコル要件を満たします。例えば:


  1. protocol SomeProtocol {
  2. static var someValue: Self { get }
  3. static func someFunction(x: Int) -> Self
  4. }
  5. enum MyEnum: SomeProtocol {
  6. case someValue
  7. case someFunction(x: Int)
  8. }


クラス型へのプロトコルの採用を制限するだけなら、コロンの後に 継承されたプロトコル のリスト内に AnyObject プロトコルを含めます。たとえば、以下のプロトコルは、クラス型によってのみ採用できます。


  1. protocol SomeProtocol: AnyObject {
  2. /* Protocol members go here */
  3. }


AnyObject 要件でマークされたプロトコルから継承する全てのプロトコルは、同様に、クラス型によってのみ採用することができます。


注意: プロトコルが objc 属性でマークされている場合は、AnyObject 要件は、暗黙のうちにそのプロトコルに適用されます。AnyObject 要件を持つプロトコルを明示的にマークする必要はありません。


プロトコルは、名前の付いた型であり、型としてのプロトコル で説明したように、それらは、他の名前の付いた型としてコード内のすべての同じ場所に表示することができます。しかし、プロトコルは実際にはそれらが指定した要件の実装を提供しないので、プロトコルのインスタンスを構築することはできません。


デリゲート で説明したように、プロトコルを使用して、クラスまたは構造体のデリゲートが実装すべきメソッドを宣言することができます。



プロトコル宣言の文法

protocol-declarationattributes ­opt access-level-modifier ­opt ­protocol protocol-name­ type-inheritance-clause ­opt generic-where-clause ­opt ­protocol-body
protocol-nameidentifier
protocol-body protocol-members ­opt ­}

protocol-membersprotocol-member protocol-members ­opt
­ protocol-memberprotocol-member-declaration ­| compiler-control-statement

protocol-member-declarationprotocol-property-declaration
protocol-member-declarationprotocol-method-declaration
protocol-member-declarationprotocol-initializer-declaration
protocol-member-declarationprotocol-subscript-declaration
protocol-member-declarationprotocol-associated-type-declaration
protocol-member-declarationstypealias-declaration­



プロトコルプロパティ宣言


プロトコルは、それに準拠した型は、プロトコル宣言の本体内に プロトコルプロパティ宣言 を含めることで、プロパティを実装しなければならないことを宣言します。プロトコルプロパティ宣言は変数宣言の特別な形式です:


­

var : { get set }



他のプロトコルメンバ宣言と同様に、これらのプロパティ宣言は、プロトコルに準拠する型用のゲッタとセッタの要件だけを宣言します。その結果、それが宣言されているプロトコルで直接ゲッタとセッタを実装しません。


ゲッタとセッタの要件は、準拠する型によってさまざまな方法で満たされます。プロパティ宣言が、getset キーワードの両方を含んでいる場合、準拠する型は読み書き可能 (つまり、ゲッタとセッタの両方を実装するもの) な格納された変数プロパティまたは計算されたプロパティでそれを実装できます。しかし、そのプロパティ宣言は、定数プロパティや読み取り専用の計算されたプロパティとしては実装できません。プロパティ宣言が get キーワードのみを含む場合は、プロパティの任意の種類として実装できます。プロトコルプロパティの要件を実装する型を準拠する例については、プロパティの要件 を参照してください。


プロトコル宣言で型プロパティ要件を宣言するには、static キーワードでプロパティ宣言をマークします。プロトコルに準拠する構造体と列挙型は、static キーワードを使用してプロパティを宣言し、プロトコルに準拠するクラスは、static または class キーワードを使用してプロパティを宣言します。構造体、列挙型、またはクラスにプロトコル準拠を追加する拡張機能は、拡張する型が使用すると同じキーワードを使用します。型プロパティ要件のデフォルトの実装を提供する拡張機能は、static キーワードを使用します。


変数の宣言 も参照してください。



プロトコルプロパティ宣言の文法

protocol-property-declarationvariable-declaration-head ­variable-name ­type-annotation getter-setter-keyword-block



プロトコルメソッド宣言


プロトコルは、それに準拠した型が、プロトコル宣言の本体内にプロトコルメソッド宣言を含めることで、メソッドを実装しなければならないことを宣言します。プロトコルメソッド宣言は、2つの例外を除いて関数宣言と同じ形式です。それらは、関数本体を含みませんし、関数宣言の一部として、デフォルトのパラメータ値を提供することは全くできません。プロトコルメソッドの要件を実装する準拠型の例については、メソッドの要件 を参照してください。


プロトコル宣言内でクラスまたは静的メソッドの要件を宣言するには、static 宣言修飾子でメソッド宣言をマークして下さい。プロトコルに準拠する構造体と列挙型は、static キーワードでメソッドを宣言し、プロトコルに準拠するクラスは、static または class キーワードでメソッドを宣言します。プロトコルの準拠性を構造体、列挙型、またはクラスに追加する拡張機能は、拡張する型が使用するのと同じキーワードを使用します。型メソッド要件のデフォルトの実装を提供する拡張機能では、static キーワードを使用します。


関数の宣言 も参照してください。


プロトコルメソッド宣言の文法

protocol-method-declarationfunction-head ­function-name generic-parameter-clause ­opt function-signature generic-where-clause ­opt



プロトコルイニシャライザ宣言


プロトコルは、それに準拠した型が、プロトコル宣言の本体内にプロトコルイニシャライザ宣言を含めることで、イニシャライザを実装しなければならないことを宣言します。プロトコルイニシャライザ宣言は、イニシャライザの本体を含まない事を除いて、イニシャライザの宣言と同じ形式を持っています。


準拠する型は、失敗できないイニシャライザまたは init! の失敗可能なイニシャライザを実装することで、失敗できないプロトコルイニシャライザの要件を満たすことができます。準拠する型は、イニシャライザのいずれかの種類を実装することで、失敗可能なプロトコルイニシャライザの要件を満たすことができます。


クラスが、プロトコルのイニシャライザ要件を満たすためにイニシャライザを実装する場合は、クラスがすでに final 宣言修飾子でマークされていなければ、イニシャライザは、required 宣言修飾子でマークされなければなりません。


イニシャライザ宣言 も参照してください。



プロトコルイニシャライザ宣言の文法

protocol-initializer-declarationinitializer-head generic-parameter-clause ­opt parameter-clause throws ­opt generic-where-clause ­opt
protocol-initializer-declarationinitializer-head generic-parameter-clause ­opt parameter-clause rethrows generic-where-clause ­opt



プロトコルサブスクリプト宣言


プロトコルは、それに準拠した型が、プロトコル宣言の本体内にプロトコルサブスクリプト宣言を含めることで、サブスクリプトを実装しなければならないことを宣言します。プロトコルサブスクリプト宣言は、サブスクリプト宣言の特殊な形式です。


subscript ( ) -> { get set }



サブスクリプト宣言は、プロトコルに準拠する型の最小限のゲッタとセッタの実装要件のみを宣言します。サブスクリプト宣言が get および set キーワード両方を含んでいる場合は、準拠型はゲッタとセッタ節両方を実装しなければなりません。サブスクリプト宣言が get キーワードのみを含んでいる場合は、準拠型は 少なくとも ゲッタ節を実装しなければならず、オプションでセッタ節を実装できます。


プロトコル宣言で静的なサブスクリプト要件を宣言するには、static 宣言修飾子を使用してサブスクリプト宣言をマークします。プロトコルに準拠する構造体と列挙型は、static キーワードでサブスクリプトを宣言し、プロトコルに準拠するクラスは、static または class キーワードでサブスクリプトを宣言します。構造体、列挙型、またはクラスにプロトコル準拠を追加する拡張機能は、拡張する型が使用するのと同じキーワードを使用します。静的サブスクリプト要件のデフォルト実装を提供する拡張機能は、static キーワードを使用します。


サブスクリプト宣言 も参照してください。



プロトコルサブスクリプト宣言の文法

protocol-subscript-declarationsubscript-head­ subscript-result generic-where-clause ­opt getter-setter-keyword-block­



プロトコルに関連した型の宣言


プロトコルは、associatedtype キーワードを使用して、関連する型を宣言します。関連する型は、プロトコル宣言の一部として使用されている型エイリアスを提供します。関連する型は、汎用パラメータ節の型パラメータに似ていますが、それらが宣言されているプロトコルでの Self に関連しています。その文脈で、Self はプロトコルに準拠する、最終的な型を参照します。詳細および例については、関連型 を参照してください。


関連型を再宣言することなく、プロトコル宣言で汎用の where 節を使用して、別のプロトコルから継承した関連型に制約を追加して下さい。たとえば、以下の SubProtocol の宣言は同等です。


  1. protocol SomeProtocol {
  2. associatedtype SomeType
  3. }
  4. protocol SubProtocolA: SomeProtocol {
  5. // This syntax produces a warning.
  6. associatedtype SomeType: Equatable
  7. }
  8. // This syntax is preferred.
  9. protocol SubProtocolB: SomeProtocol where SomeType: Equatable {}


型エイリアス宣言 も参照してください。



プロトコルに関連した型の宣言の文法

protocol-associated-type-declarationattributes ­opt access-level-modifier ­opt ­associatedtype typealias-name ­type-inheritance-clause ­­opt ­typealias-assignment ­opt generic-where-clause ­opt



イニシャライザ宣言


イニシャライザ宣言 はプログラムに、クラス、構造体、または列挙型のイニシャライザを導入します。イニシャライザ宣言は、init キーワードを使用して宣言し、2つの基本的な形式があります。


構造体、列挙型、およびクラス型は、いくつでもイニシャライザを持てますが、クラスイニシャライザのための規則と関連した動作は異なっています。構造体や列挙型とは異なり、クラスには2種類のイニシャライザがあります:指定イニシャライザとコンビニエンス・イニシャライザです。詳しくは 初期化 を参照して下さい。


以下の形式は、構造体、列挙型のイニシャライザ、およびクラスの指定イニシャライザを宣言しています。


init ( ) {
       
}


クラスの指定イニシャライザは、直接クラスのすべてのプロパティを初期化します。それは、同じクラスの他のイニシャライザを呼び出すことは全くできず、クラスがスーパークラスを持つ場合、スーパークラスの指定イニシャライザのいずれか一つを呼び出さなければなりません。クラスがそのスーパークラスからいくつかプロパティを継承する場合、これらのプロパティのいずれかが現在のクラスで設定されまたは変更される前に、スーパークラスの指定イニシャライザの一つが呼び出されなければなりません。


指定イニシャライザは、クラス宣言の文脈の中でのみ宣言できるため、拡張機能の宣言を使用してクラスに追加はできません。


構造体や列挙型におけるイニシャライザは、初期化プロセスの一部またはすべてをデリゲートする他の、宣言されたイニシャライザを呼び出すことができます。


クラスのコンビニエンスイニシャライザを宣言するには、convenience 宣言修飾子でイニシャライザ宣言をマークして下さい。


convenience init ( ) {
       
}


コンビニエンスイニシャライザは、他のコンビニエンスイニシャライザまたはクラスの指定イニシャライザのいずれか一つに、初期化プロセスをデリゲートすることができます。つまり、初期化プロセスは、最終的には、クラスのプロパティを初期化する指定イニシャライザへの呼び出しで終了しなければなりません。コンビニエンスイニシャライザは、スーパークラスのイニシャライザを呼び出すことはできません。


required 宣言修飾子で指定イニシャライザとコンビニエンスイニシャライザをマークし、すべてのサブクラスでイニシャライザを実装することを要求できます。そのイニシャライザのサブクラスの実装も、 required 宣言修飾子でマークされなければなりません。


デフォルトでは、スーパークラスで宣言されたイニシャライザはサブクラスによっては継承されません。つまり、サブクラスがデフォルト値で、その格納されたすべてのプロパティを初期化し、独自のイニシャライザを全く定義していない場合には、スーパークラスのすべてのイニシャライザを継承します。サブクラスがスーパークラスの指定イニシャライザのすべてをオーバーライドする場合、それはスーパークラスのコンビニエンスイニシャライザを継承します。


メソッド、プロパティ、およびサブスクリプトと同様に、override 宣言修飾子で、オーバーライドされた指定イニシャライザをマークする必要があります。


注意: required 宣言修飾子でイニシャライザをマークした場合、サブクラス内で必須イニシャライザを上書きするときには、override 修飾子でイニシャライザをまたマークしないでください。


関数やメソッドと全く同様に、イニシャライザはエラーを throw または rethrow できます。また、関数やメソッドと全く同様に、イニシャライザのパラメータの後に throws または rethrows キーワードを使用して、適切な動作を示して下さい。


さまざまな型宣言のイニシャライザの例を参照するには、初期化 を参照してください。


失敗可能イニシャライザ


失敗可能イニシャライザ (failable initializer) は、optional のインスタンスまたはイニシャライザが宣言されている型の暗黙的に開封された optional のインスタンスを生成するイニシャライザの一つの型です。その結果、失敗可能イニシャライザは、初期化に失敗した事を示すため nil を返すことができます。


optional のインスタンスを生成する失敗可能イニシャライザを宣言するには、イニシャライザの宣言の init キーワードに疑問符を追加 (init?) します。暗黙的に開封された optional のインスタンスを生成する失敗可能イニシャライザを宣言するには、代わりに感嘆符を追加 (init!) します。以下の例は、構造体の optional のインスタンスを生成する init? の失敗可能イニシャライザの例を示しています。


  1. struct SomeStruct {
  2. let property: String
  3. // produces an optional instance of 'SomeStruct'
  4. init?(input: String) {
  5. if input.isEmpty {
  6. // discard 'self' and return 'nil'
  7. return nil
  8. }
  9. property = input
  10.     }
  11. }


結果の optional 性に対処しなければならないことを除いては、失敗できないイニシャライザを呼び出すのと同じ方法で init? の失敗可能イニシャライザを呼び出せます。


  1. if let actualInstance = SomeStruct(input: "Hello") {
  2. // do something with the instance of 'SomeStruct'
  3. } else {
  4. // initialization of 'SomeStruct' failed and the initializer returned 'nil'
  5. }


失敗可能イニシャライザは、イニシャライザの本体の実装の任意の時点で nil を返すことができます。


失敗可能イニシャライザはどのような種類のイニシャライザにもデリゲートできます。失敗できないイニシャライザは、他の失敗できないイニシャライザまたは init! の失敗可能イニシャライザにデリゲートできます。失敗できないイニシャライザは、スーパークラスのイニシャライザの結果を強制開封することにより、init? の失敗可能イニシャライザにデリゲートできます–例えば、super.ini()! と書くことによって。


初期化失敗はイニシャライザのデリゲートを介して伝播します。具体的には、失敗可能イニシャライザが、失敗して nil を返すイニシャライザにデリゲートする場合、デリゲートされたイニシャライザも失敗し、暗黙的に nil を返します。失敗できないイニシャライザが失敗して nil を返す init! の失敗可能イニシャライザにデリゲートすると、実行時エラーが発生します (! 演算子を使用して、nil 値を持つ optional を開封した場合のように)。


失敗可能指定イニシャライザは、指定イニシャライザのどの種類によってもサブクラス内でオーバーライドできます。失敗できない指定イニシャライザは、失敗できない指定イニシャライザによってのみサブクラス内でオーバーライドできます。


詳細と失敗可能イニシャライザの例を見るには、失敗可能イニシャライザ を参照してください。



イニシャライザ宣言の文法

initializer-declarationinitializer-head< generic-parameter-clause ­opt parameter-clause throws ­opt generic-where-clause ­opt initializer-body
initializer-declarationinitializer-head generic-parameter-clause ­opt parameter-clause rethrows generic-where-clause ­opt initializer-body
initializer-headattributes ­opt ­declaration-modifiers ­opt ­init
­ initializer-headattributes ­opt declaration-modifiers ­opt ­init­ ?
initializer-headattributes ­opt declaration-modifiers ­opt ­init­ !
­ initializer-bodycode-block



デイニシャライザ宣言


デイニシャライザ宣言 はクラス型のためのデイニシャライザを宣言します。デイニシャライザはパラメータを全くとらず、以下の形式です:


deinit {
       
}


クラスオブジェクトへの参照がもはやない場合に、クラスオブジェクトが割り当て解除される直前にデイニシャライザは自動的に呼び出されます。デイニシャライザは、クラス宣言の本体内でのみ宣言できますが、クラスの拡張機能の中では宣言できず、各クラスは最大一つデイニシャライザを持つことができます。


サブクラスは、そのスーパークラスのデイニシャライザを継承し、サブクラスオブジェクトが割り当て解除される直前に暗黙的に呼び出されます。サブクラスオブジェクトは、その継承連鎖のすべてのデイニシャライザの実行が終了するまで、割り当て解除されません。


デイニシャライザは直接呼び出されません。


クラス宣言内でデイニシャライザを使用する方法の例については、デイニシャライザ を参照してください。


デイニシャライザ宣言の文法

deinitializer-declarationattributes ­opt ­deinit code-block



拡張機能の宣言


拡張機能の宣言 では、既存の型の動作を拡張できます。拡張機能の宣言は、extension キーワードを使用して宣言し、以下のような形式です:


extension where {
       
}


拡張機能の宣言の本体は、ゼロ個以上の 宣言 を含んでいます。これらの 宣言 は、計算されたプロパティ、計算された型プロパティ、インスタンスメソッド、型メソッド、イニシャライザ、サブスクリプト宣言、さらにはクラス、構造体、および列挙型宣言を含めることができます。拡張機能の宣言にはデイニシャライザまたはプロトコル宣言、格納されたプロパティ、プロパティ監視者、または他の拡張機能の宣言を含めることはできません。プロトコル機能拡張内の宣言には final でマークをすることはできません。拡張機能の議論や宣言の様々な種類を含むいくつかの例については、拡張機能 を参照してください。


型名 がクラス、構造体または列挙型の場合、拡張機能はその型を拡張します。型名 がプロトコル型の場合、拡張機能はそのプロトコルに準拠するすべての型を拡張します。


関連する型を持つプロトコルまたは汎用型を拡張する拡張機能の宣言には、要件 を含めることができます。拡張型または拡張プロトコルに準拠する型のインスタンスが 要件 を満たす場合、そのインスタンスは宣言で指定された動作を取得します。


拡張機能の宣言はイニシャライザ宣言を含むことができます。つまり、拡張しようとする型が別のモジュールで定義されている場合、イニシャライザ宣言は、その型のメンバが正しく初期化されるように、そのモジュールですでに定義されているイニシャライザにデリゲートしなければなりません。


既存の型のプロパティ、メソッド、およびイニシャライザはその型の拡張機能内でオーバーライドすることはできません。


拡張機能の宣言は、採用されているプロトコル を指定することによって、既存のクラス、構造体、または列挙型にプロトコル準拠を追加できます:


extension : where {
       
}


拡張伊能の宣言では既存のクラスにクラスの継承を追加できないため、型名 とコロンの後にプロトコルのリストのみを指定できます。


条件付きの準拠


条件付きでプロトコルに準拠するように汎用型を拡張して、特定の要件が満たされた場合にのみその型のインスタンスがプロトコルに準拠するようにできます。拡張機能の宣言に 要件 を含めることによって、プロトコルに条件付き準拠を追加して下さい。


オーバーライドされた要件はいくつかの汎用コンテキストでは使用されない


いくつかの汎用の文脈 (context) では、条件付き準拠からプロトコルへの動作を得る型は、常にそのプロトコルの要件の特殊な実装を使用するとは限りません。この動作を説明するために、以下の例では 2 つのプロトコルと、条件付きで両方のプロトコルに準拠する汎用型を定義しています。


  1. protocol Loggable {
  2. func log()
  3. }
  4. extension Loggable {
  5. func log() {
  6. print(self)
  7. }
  8. }
  9. protocol TitledLoggable: Loggable {
  10. static var logTitle: String { get }
  11. }
  12. extension TitledLoggable {
  13. func log() {
  14. print("\(Self.logTitle): \(self)")
  15. }
  16. }
  17. struct Pair<T>: CustomStringConvertible {
  18. let first: T
  19. let second: T
  20. var description: String {
  21. return "(\(first), \(second))"
  22. }
  23. }
  24. extension Pair: Loggable where T: Loggable { }
  25. extension Pair: TitledLoggable where T: TitledLoggable {
  26. static var logTitle: String {
  27. return "Pair of '\(T.logTitle)'"
  28. }
  29. }
  30. extension String: TitledLoggable {
  31. static var logTitle: String {
  32. return "String"
  33. }
  34. }


Pair 構造体は、その汎用型がそれぞれ Loggable または TitledLoggable に準拠している場合は常に Loggable および TitledLoggable に準拠しています。以下の例では、oneAndTwoPair<String> のインスタンスであり、これは StringTitledLoggable に準拠しているため、TitledLoggable に準拠しています。log() メソッドが oneAndTwo で直接呼び出されると、タイトルの文字列を含む特殊なバージョンが使用されます。


  1. let oneAndTwo = Pair(first: "one", second: "two")
  2. oneAndTwo.log()
  3. // Prints "Pair of 'String': (one, two)"


ただし、oneAndTwo が汎用のコンテキストで使用されたり、Loggable プロトコルのインスタンスとして使用される場合は、特別なバージョンは使用されません。Swift は、PairLoggable に準拠するために必要な最小限の要件のみを調べることによって、呼び出す log() の実装を選択します。このため、Loggable プロトコルで提供されているデフォルトの実装が代わりに使用されます。


  1. func doSomething<T: Loggable>(with x: T) {
  2. x.log()
  3. }
  4. doSomething(with: oneAndTwo)
  5. // Prints "(one, two)"


doSomething(_:) に渡されたインスタンスで log() が呼び出されると、カスタマイズされたタイトルはログに記録された文字列から省略されます。


プロトコル準拠性は冗長であってはならない


具象的な型は、特定のプロトコルに一度だけ準拠できます。Swift は冗長なプロトコル準拠性をエラーとしてマークします。2 種類の状況でこの種のエラーに遭遇する可能性があります。最初の状況は、同じプロトコルに複数回明示的に準拠しているが、要件が異なる場合です。2 番目の状況は、暗黙的に同じプロトコルから複数回継承する場合です。これらの状況については、以下のセクションで説明します。


明示的な冗長性の解決


拡張機能の要件が相互に排他的であっても、具象的な型の複数の拡張機能は、同じプロトコルへの準拠性を追加することはできません。この制限は、以下の例で説明します。2 つの拡張機能の宣言は、Serializable プロトコルに条件付き準拠を追加しようとします。1 つは Int 要素を持つ配列用、もう 1 つは String 要素を持つ配列用です。


  1. protocol Serializable {
  2. func serialize() -> Any
  3. }
  4. extension Array: Serializable where Element == Int {
  5. func serialize() -> Any {
  6. // implementation
  7. }
  8. }
  9. extension Array: Serializable where Element == String {
  10. func serialize() -> Any {
  11. // implementation
  12. }
  13. }
  14. // Error: redundant conformance of 'Array<Element>' to protocol 'Serializable'


複数の具体的な型に基づく条件付き準拠を追加する必要がある場合は、各型が準拠できる新しいプロトコルを作成し、条件付き準拠を宣言するときの要件としてそのプロトコルを使用します。


  1. protocol SerializableInArray { }
  2. extension Int: SerializableInArray { }
  3. extension String: SerializableInArray { }
  4. extension Array: Serializable where Element: SerializableInArray {
  5. func serialize() -> Any {
  6. // implementation
  7. }
  8. }


暗黙的な冗長性の解決


具体的な型が条件付きでプロトコルに準拠している場合、その型は暗黙のうちに同じ要件を持つ親プロトコルに準拠しています。


単一の親から継承する 2 つのプロトコルに条件付きで準拠する型が必要な場合は、親プロトコルへの準拠を明示的に宣言してください。これにより、異なる要件で 2 回親プロトコルに暗黙的に準拠することが回避されます。


以下の例では、TitledLoggable プロトコルと新しい MarkedLoggable プロトコルの両方に条件付きで準拠することを宣言するときに競合を避けるために、Array から Loggable への条件付き準拠を明示的に宣言しています。


  1. protocol MarkedLoggable: Loggable {
  2. func markAndLog()
  3. }
  4. extension MarkedLoggable {
  5. func markAndLog() {
  6. print("----------")
  7. log()
  8. }
  9. }
  10. extension Array: Loggable where Element: Loggable { }
  11. extension Array: TitledLoggable where Element: TitledLoggable {
  12. static var logTitle: String {
  13. return "Array of '\(Element.logTitle)'"
  14. }
  15. }
  16. extension Array: MarkedLoggable where Element: MarkedLoggable { }


Loggable への条件付き準拠を明示的に宣言する拡張機能がなければ、他の Array の拡張機能は暗黙的にこれらの宣言を作成し、結果としてエラーになります。


  1. extension Array: Loggable where Element: TitledLoggable { }
  2. extension Array: Loggable where Element: MarkedLoggable { }
  3. // Error: redundant conformance of 'Array<Element>' to protocol 'Loggable'


機能拡張の宣言の文法

extension-declarationattributes ­opt access-level-modifier opt ­extension type-identifier type-inheritance-clause ­opt ­generic-where-clause extension-body
extension-body extension-members ­opt ­}

extension-membersextension-member­ extension-members ­opt­
extension-memberdeclaration | compiler-control-statement
­


サブスクリプト宣言


サブスクリプト 宣言では、特定の型のオブジェクトのサブスクリプトサポートを追加し、コレクション、リスト、またはシーケンス内の要素にアクセスするための便利な構文を提供するために典型的に使用できるようにします。サブスクリプト宣言は subscript キーワードを使用して宣言し、以下のような形式です:


subscript ( ) -> {
        get {
               
        }
        set( ) {
               
        }
}


サブスクリプト宣言は、クラス、構造体、列挙型、拡張機能、またはプロトコル宣言の文脈にのみ現れます。


パラメータ は、サブスクリプト式に対応する型の要素にアクセスするために使用される1つ以上のインデックスを指定します (例えば、式 object[i] での i)。要素にアクセスするために使用されるインデックスは任意の型のものですが、それぞれのパラメータには、各インデックスの型を指定するための型注釈を含めなければなりません。戻り値の型 は、アクセスされている要素の型を指定します。


計算されたプロパティと同様に、サブスクリプト宣言は、アクセスした要素の値を読み書きするサポートをします。ゲッタは、値を読み出すために使用され、セッタは、値を書き込むために使用されます。セッタ節はオプションで、ゲッタだけが必要なときには、両方の節を省略して、要求された値を直接単に返せます。つまり、セッタ節を提供する場合、ゲッタ節も提供しなければなりません。


セッタ名 とそれを囲む括弧はオプションです。セッタ名を提供する場合は、セッタへのパラメータの名前としてそれは使用されます。セッタ名を提供しない場合は、セッタへのデフォルトのパラメータ名は value です。セッタへのパラメータ型は、戻り値の型 と同じです。


パラメータ戻り値の型 が、オーバーロードしたものと異なる限り、それが宣言されている型でのサブスクリプト宣言をオーバーロードできます。また、スーパークラスから継承されたサブスクリプト宣言をオーバーライドする事もできます。これを行う時は、override 宣言修飾子でオーバーライドされたサブスクリプト宣言をマークしなければなりません。


サブスクリプトパラメータは、2 つの例外を除いて、関数パラメータと同じ規則に従います。デフォルトでは、サブスクリプトで使用されるパラメータには、関数、メソッド、およびイニシャライザとは異なり、引数ラベルはありません。ただし、関数、メソッド、およびイニシャライザが使用するのと同じ構文を使用して、明示的な引数ラベルを提供できます。また、サブスクリプトには in-out パラメータを指定できません。パラメータの特殊な種類 で説明した構文を使用して、サブスクリプトパラメータにデフォルト値を設定できます。


プロトコルサブスクリプト宣言 で説明したように、プロトコル宣言の文脈でサブスクリプトを宣言する事もできます。


サブスクリプト宣言の例の参照と詳細については、サブスクリプト を参照してください。


型サブスクリプト宣言


型のインスタンスによってではなく、型によって公開されるサブスクリプトを宣言するには、サブスクリプト宣言を static 宣言修飾子でマークします。クラスは、スーパークラスの実装をサブクラスがオーバーライドするのを許可する代わりに class 宣言修飾子で型の計算されたプロパティをマークできます。クラス宣言では、static キーワードは、classfinal の宣言修飾子の両方で宣言をマークするのと同じ効果があります。


サブスクリプト宣言の文法

subscript-declarationsubscript-head subscript-result generic-where-clause opt ­code-block
subscript-declarationsubscript-head ­subscript-result generic-where-clause opt getter-setter-block
subscript-declarationsubscript-head ­subscript-result generic-where-clause opt getter-setter-keyword-block
subscript-headattributes ­opt declaration-modifiers ­opt ­subscript generic-parameter-clause ­opt
subscript-result->
attributes ­opt ­type



演算子の宣言


演算子の宣言 は、プログラムに新しい挿入辞、接頭辞、または接尾辞演算子を導入し、operator キーワードを使用して宣言されます。


挿入辞、接頭辞および接尾辞の、3つの異なる定着演算子を宣言できます。演算子の 定着性 は、そのオペランドへの演算子の相対的な位置を指定します。


演算子の宣言の3つの基本的な形式は、それぞれの定着性に一つずつあります。演算子の定着性は、operator キーワードの前に infix,prefix または postfix 宣言修飾子で演算子の宣言をマークすることによって指定されます。各形式では、演算子の名前は、演算子 で定義された演算子の文字のみを含めることができます。


以下の形式で、新しい挿入辞演算子を宣言します。


infix operator :



挿入辞演算子 は、式 1 + 2 でおなじみの加算演算子 (+) のような、2つのオペランドの間に書かれる二項演算子です。


挿入辞演算子は、オプションで優先順位グループを指定できます。演算子の優先順位グループを省略すると、Swift はデフォルトの優先順位グループ DefaultPrecedence を使用します。これは、TernaryPrecedence よりも 1 つだけ高い優先順位を指定します。詳細については、優先順位グループ宣言 を参照してください。


以下の形式で、新しい接頭辞演算子を宣言します。


prefix operator



接頭辞演算子 は、式 !a での接頭辞論理 NOT 演算子 (!) のような、そのオペランドの直前に書かれた単項演算子です。


接頭辞演算子の宣言では、優先順位レベルは指定されません。接頭辞演算子は非結合性です。


以下の形式で、新しい接尾辞演算子を宣言します。


postfix operator



接尾辞演算子 は、式 a! での接尾辞強制開封演算子 (!) のような、そのオペランドの直後に書かれる単項演算子です。


接頭辞演算子と同様に、接尾辞演算子宣言は優先順位レベルを指定しません。接尾辞演算子は非結合性です。


新しい演算子を宣言した後は、その演算子と同じ名前の静的メソッドを宣言してそれを実装します。静的メソッドは、演算子が引数として取る値の 1 つの型のメンバです。たとえば、DoubleInt を乗算する演算子は、Double または Int 構造体のいずれかに静的メソッドとして実装されます。接頭辞または接尾辞演算子を実装している場合は、そのメソッド宣言に対応する prefix または postfix 宣言修飾子をも付けてマークしなければなりません。新しい演算子を作成して実装する方法の例については、カスタム演算子 を参照してください。


演算子の宣言の文法

operator-declarationprefix-operator-declarationpostfix-operator-declarationinfix-operator-declaration­

prefix-operator-declarationprefix ­operator ­operator
postfix-operator-declarationpostfix ­operator ­operator
infix-operator-declarationinfix­ operator ­operator ­infix-operator-grou ­opt

infix-operator-group: precedence-group-name



優先順位グループ宣言


優先順位グループ宣言 では、挿入辞演算子の優先順位をプログラムに追加するための新しいグループを導入します。演算子の優先順位は、括弧をグループ化していない場合、演算子がそのオペランドにどれくらい緊密に結合するかを指定します。


優先順位グループ宣言の形式は以下のとおりです。


precedencegroup {
        higherThan:
        lowerThan:
        associativity:
        assignment:
}


低い順位のグループ名 および 高い順位のグループ名 のリストは、新しい優先順位グループと既存の優先順位グループとの関係を指定します。lowerThan の優先順位のグループ属性は、現在のモジュールの外部で宣言された優先順位グループを参照するためにのみ使用できます。2つの演算子が式 2 + 3 * 5 のようにそのオペランドで互いに競合する場合、相対的に優先順位の高い演算子がそのオペランドにより強く結びつきます。


注意: 低い順位のグループ名高い順位のグループ名 を使用して相互に関係する優先順位グループは、1つの関係する階層に収まらなければなりませんが、線形階層を形成する必要は ありません。つまり、相対的な優先順位が未定義の優先順位グループを持つことができる事を意味します。これらの優先順位グループの演算子は、括弧をグループ化することなく、互いに隣り合って使用することはできません。


Swift は、標準ライブラリによって提供される演算子と一緒にするために多数の優先順位グループを定義しています。たとえば、加算 (+) および減算 (-) 演算子は AdditionPrecedence グループに属し、乗算 (*) および除算 (/) 演算子は MultiplicationPrecedence グループに属します。Swift 標準ライブラリが提供する優先順位グループの完全なリストについては、演算子の宣言 を参照してください。


演算子の 結合性 は、グループ化する括弧が存在しない場合に、同じ優先順位レベルを持つ演算子のシーケンスをどのようにグループ化するかを指定します。文脈依存のキーワードを1つ、left、right または none のいずれかを書くことによって、演算子の結合性を指定します。結合性を省略すると、デフォルトは none になります。左結合グループである演算子は左から右へグループになります。たとえば、減算演算子 (-) は左結合性であるため、式 4 - 5 - 6(4 - 5) - 6 とグループ化され、-7 と評価されます。none の結合性の演算子は、まったく結合しません。同じ優先順位レベルの非結合演算子は、互いに隣接して現れることはできません。たとえば、< 演算子は、none の結合性を持ち、1 < 2 < 3 は有効な式ではないことを意味します。


優先順位グループの 代入 は、optional の連鎖を含む演算で使用される場合、演算子の優先順位を指定します。true に設定すると、対応する優先順位グループの演算子は、標準ライブラリからの代入演算子として、optional の連鎖中に同じグループ化規則を使用します。それ以外の場合、false に設定するか省略すると、優先順位グループの演算子は、代入を実行しない演算子と同じ optional の連鎖規則に従います。


優先順位グループ宣言の文法

precedence-group-declarationprecedencegroup ­precedence-group-name­ { ­precedence-group-attributes ­opt ­}
precedence-group-attributesprecedence-group-attribute ­precedence-group-attributes ­opt
­ precedence-group-attributerecedence-group-relation
precedence-group-attributeprecedence-group-assignment
precedence-group-attributeprecedence-group-associativity

precedence-group-relationhigherThan ­: ­precedence-group-names
precedence-group-relationlowerThan ­: ­precedence-group-names

precedence-group-assignmentassignment ­: ­boolean-literal

precedence-group-associativityassociativity­ : ­left
precedence-group-associativityassociativity ­: ­right
precedence-group-associativityassociativity ­: ­none
precedence-group-namesprecedence-group-name | precedence-group-name ­, ­precedence-group-names
precedence-group-nameidentifier­



宣言修飾子



宣言修飾子 は、キーワードまたは宣言の動作や意味を変更する文脈に敏感なキーワードです。適切なキーワードまたは宣言の属性 (もしあれば) の間の文脈に敏感なキーワード及び宣言を導入するキーワードを書くことによって宣言修飾子を指定して下さい。



class

この修飾子をクラスのメンバに適用して、そのメンバがクラスのインスタンスのメンバではなく、クラス自体のメンバであることを示します。この修飾子を持ち、final 修飾子を持たないスーパークラスのメンバは、サブクラスでオーバーライドできます。


dynamic

Objective-C で表されるクラスの任意のメンバにこの修飾子を適用します。dynamic 修飾子でメンバ宣言をマークすると、そのメンバへのアクセスは常に Objective-C の実行時環境を使用して動的に送出されます。そのメンバへのアクセスは、コンパイラによって全くインライン化されず、仮想化されません。

dynamic 修飾子でマークされる宣言は、Objective-C 実行時環境を使用して送出されるので、それらは objc 属性でマークされなければなりません。


final

クラスまたはクラスのプロパティ、メソッド、またはサブスクリプトメンバにこの修飾子を適用して下さい。これは、クラスがサブクラス化できないことを示すためにクラスに適用されます。クラスのメンバは全てのサブクラスでオーバーライドできないことを示すために、クラスのプロパティ、メソッド、またはサブスクリプトにこれは適用されます。final 属性の使用例については、オーバーライドの防止 を参照してください。


lazy

プロパティの初期値が計算され、多くとも1回、プロパティに最初にアクセスしたときに格納されることを示すために、クラスまたは構造体の格納された変数プロパティに、この修飾子を適用して下さい。lazy 修飾子を使用する方法の例については、遅延した格納されたプロパティ を参照してください。


optional

準拠する型はそれらのメンバを実装するのに必須ではないことを示すために、プロトコルのプロパティ、メソッド、またはサブスクリプトメンバに、この修飾子を適用します。

objc 属性でマークされているプロトコルにのみ、optional 修飾子を適用できます。その結果、クラス型だけが、optional のメンバ要件を含むプロトコルを採用し、準拠できます。optional 修飾子を使用する詳しい方法と optional プロトコルメンバにアクセスする方法のガイドについては、例えば、準拠型がそれらを実装しているかどうかわからない時は、Optional のプロトコル要件 を参照してください。


required

すべてのサブクラスが、そのイニシャライザを実装しなければならないことを示すために、クラスの指定イニシャライザ、またはコンビニエンス・イニシャライザに、この修飾子を適用します。そのイニシャライザのサブクラスの実装も、required 修飾子でマークされなければなりません。


static

この修飾子を構造体、クラス、列挙型、またはプロトコルのメンバに適用して、メンバがその型のインスタンスのメンバではなく、その型のメンバであることを示します。クラス宣言のスコープでは、メンバ宣言に static 修飾子を記述すると、そのメンバ宣言に class 修飾子と final 修飾子を記述するのと同じ効果があります。ただし、クラスの定数型プロパティは例外です。class または final をこれらの宣言で記述できないため、static は、通常の、クラスでない意味があります。


unowned

この修飾子を、格納された変数、定数、または格納されたプロパティに適用して、変数またはプロパティがその値として格納されたオブジェクトへの所有されていない参照を持つことを示します。オブジェクトが割り当てを解除された後に変数またはプロパティにアクセスしようとすると、実行時エラーが発生します。弱い参照と同様に、プロパティ型または値型はクラス型でなければなりません。弱い参照とは異なり、型は optional ではありません。unowned 修飾子の例と詳細については、所有されていない参照 を参照してください。


unowned(safe)

unowned の明示的な綴り。


unowned(unsafe)

この修飾子を、格納された変数、定数、または格納されたプロパティに適用して、変数またはプロパティがその値として格納されたオブジェクトへの所有されていない参照を持つことを示します。オブジェクトが割り当てを解除された後に変数またはプロパティにアクセスしようとすると、オブジェクトが存在していた場所のメモリにアクセスします。これはメモリが安全でない操作です。弱い参照と同様に、プロパティ型または値型はクラス型でなければなりません。弱い参照とは異なり、型は optional ではありません。 unowned 修飾子の例と詳細については、所有されていない参照 を参照してください。


weak

この修飾子を、格納された変数または格納された変数プロパティに適用して、変数またはプロパティがその値として格納されたオブジェクトへの弱い参照を持つことを示します。変数型またはプロパティ型は、optional のクラス型でなければなりません。オブジェクトが割り当てを解除された後に変数またはプロパティにアクセスすると、その値は nil になります。weak 修飾子の例と詳細については、弱い参照 を参照してください。



アクセス制御レベル


Swift は、アクセス制御に五つのレベルを提供します:open,public,internal,file private, および private です。宣言のアクセスレベルを指定するには、以下のアクセス·レベルの修飾子の一つで宣言をマークできます。アクセス制御は、アクセス制御 で詳細に議論しています。


open

この修飾子を宣言に適用して、宣言と同じモジュール内のコードで宣言がアクセスでき、またサブクラス化できることを示します。open のアクセスレベル修飾子でマークされた宣言は、その宣言を含むモジュールを import するモジュール内のコードによってもアクセスでき、またサブクラス化することもできます。


public

この修飾子を宣言に適用して、宣言と同じモジュール内のコードで宣言がアクセスでき、またサブクラス化できることを示します。public のアクセスレベル修飾子でマークされた宣言は、その宣言を含むモジュールを import するモジュール内のコードによってもアクセスできます (しかしサブクラス化はできません)。


internal

この修飾子を宣言に適用して、宣言と同じモジュール内のコードでのみ宣言がアクセスできることを示します。デフォルトでは、ほとんどの宣言は暗黙のうちに internal のアクセスレベル修飾子でマークされています。


fileprivate

この修飾子を宣言に適用して、宣言と同じソースファイル内のコードによってのみ宣言がアクセスできることを示します。


private

この修飾子を宣言に適用して、宣言が直接に取り囲むスコープ内のコードによってのみ宣言がアクセスできることを示します。


アクセス制御の目的で、同じファイル内の同じ型への拡張機能がアクセス制御スコープを共有します。拡張された型が同じファイル内にもある場合、型のアクセス制御スコープも共有されます。型の宣言で宣言された private メンバは、拡張機能からアクセスでき、ある拡張機能で宣言された private メンバは、他の拡張機能と型宣言からアクセスできます。


上記の各アクセスレベルの修飾子は、必要に応じて、括弧で囲まれた set キーワードで構成された一つの引数 (例えば、private(set) )を受け付けます。ゲッタとセッタ で説明したように、変数またはサブスクリプト自体のアクセスレベル以下の変数またはサブスクリプトのセッタのアクセスレベルを指定する場合、アクセスレベル修飾子のこの形式を使用します。


宣言修飾子の文法

declaration-modifierclassconvenience ­| dynamic | final | infix | lazy | optional­ | override | postfix | prefix | required | static | unowned | unowned­ ( ­safe ­) | unowned ­( ­unsafe ­)weak
declaration-modifieraccess-level-modifier
declaration-modifiermutation-modifier
declaration-modifiersdeclaration-modifier declaration-modifiers ­opt

access-level-modifierprivate | private ­( ­set ­)
access-level-modifierfileprivate­ | fileprivate ­( ­set ­)­
access-level-modifierinternal | internal ­( ­set ­)
access-level-modifierpublic | public ­( ­set ­)
access-level-modifieropen | open ­( ­set ­)

mutation-modifiermutating | nonmutating


前:文 次:属性
















トップへ












トップへ












トップへ












トップへ
目次
Xcode の新機能

Swift について
Swift と Cocoa と Objective-C (obsolete)
Swift Blog より (obsolete)

SwiftLogo
  • Swift 5.3 全メニュー


  • Swift へようこそ
  • Swift について

  • Swift 言語のガイド

  • 言語リファレンス
  • 言語リファレンスについて
  • 語彙の構造



  • 宣言
  • 属性
  • パターン
  • 汎用パラメータと引数
  • 文法のまとめ

  • マニュアルの変更履歴













  • トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ