クラス、構造体、および列挙体は、コレクション、リスト、またはシーケンスのメンバー要素にアクセスするためのショートカットであるサブスクリプトを定義できます。サブスクリプトを使用すると、設定と取得のための個別のメソッドを必要とせずに、インデックスによって値を設定および取得できます。たとえば、Array
インスタンスの要素にはsomeArray[index]として、Dictionaryインスタンスの要素にはsomeDictionary[key]としてアクセスします。
単一のタイプに対して複数のサブスクリプトを定義できます。使用する適切なサブスクリプトオーバーロードは、サブスクリプトに渡すインデックス値のタイプに基づいて選択されます。サブスクリプトは単一の次元に限定されず、カスタムタイプのニーズに合わせて複数の入力パラメーターでサブスクリプトを定義できます。
サブスクリプト構文
インスタンスメソッドとは異なり、サブスクリプトは読み取り/書き込みまたは読み取り専用にすることができます。この動作は、計算されたプロパティの場合と同じ方法でゲッターとセッターによって伝達されます。
subscript(index: Int) -> Int { get { // Return an appropriate subscript value here. } set(newValue) { // Perform a suitable setting action here. } } // 読み取り専用のサブスクリプトの宣言 subscript(index: Int) -> Int { // Return an appropriate subscript value here. } // 読み取り専用のサブスクリプトの例 struct TimesTable { let multiplier: Int subscript(index: Int) -> Int { return multiplier * index } } let threeTimesTable = TimesTable(multiplier: 3) print("six times three is \(threeTimesTable[6])") // Prints "six times three is 18"
サブスクリプトの使用
「サブスクリプト」の正確な意味は、それが使用されるコンテキストによって異なります。サブスクリプトは通常、コレクション、リスト、またはシーケンスのメンバー要素にアクセスするためのショートカットとして使用されます。特定のクラスまたは struct の機能に最適な方法でサブスクリプトを自由に実装できます。
たとえば、SwiftのDictionary
型は、Dictionary
インスタンスに格納されている値を設定および取得するためのサブスクリプトを実装しています。サブスクリプトの括弧内にDictionaryのキーを提供し、ディクショナリに値を設定できます。
var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] numberOfLegs["bird"] = 2
注意
SwiftのDictionary
型は、キーと値のサブスクリプトを、オプションの型を受け取って返すサブスクリプトとして実装します。numberOfLegs
上記のディクショナリの場合、キーと値のサブスクリプトは Int?、つまり「オプショナルint」を受け取って返します。
サブスクリプトオプション
サブスクリプトは任意の数の入力パラメーターを取ることができ、これらの入力パラメーターは任意のタイプにすることができます。サブスクリプトは、任意のタイプの値を返すこともできます。
関数と同様に、添字はさまざまな数のパラメーターを受け取り、それらのパラメーターにデフォルト値を提供できます。ただし、関数とは異なり、サブスクリプトは入出力パラメーターを使用できません。
クラスまたは構造体は、必要なだけのサブスクリプト実装を提供できます。使用される適切なサブスクリプトは、サブスクリプトが使用されているポイントでサブスクリプト括弧内に含まれている値のタイプに基づいて推測されます。この複数のサブスクリプトの定義は、サブスクリプトオーバーロードと呼ばれます。
サブスクリプトが単一のパラメーターを取るのが最も一般的ですが、複数のパラメーターを持つサブスクリプトを定義することもできます。次の例では、Doubleの2次元行列を表す構造を定義しています。Matrix
構造のサブスクリプトは、2つの整数パラメータを取ります。
struct Matrix { let rows: Int, columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } func indexIsValid(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } subscript(row: Int, column: Int) -> Double { get { assert(indexIsValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] } set { assert(indexIsValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } } // Matrix初期化子に適切な行と列の数を渡すことにより、新しいインスタンスを構築できます。 var matrix = Matrix(rows: 2, columns: 2) // 行列の値は、行と列の値をコンマで区切ってサブスクリプトに渡すことで設定できます。 matrix[0, 1] = 1.5 matrix[1, 0] = 3.2 // 行列の境界外にあるサブスクリプトにアクセスしようとすると、アサーションがトリガーされます。 let someValue = matrix[2, 2] // This triggers an assert, because [2, 2] is outside of the matrix bounds.
タイプサブスクリプト
上記のインスタンスサブスクリプトは、特定のタイプのインスタンスで呼び出すサブスクリプトです。タイプそのもので呼び出されるサブスクリプトを定義することもできます。この種のサブスクリプトは、タイプサブスクリプトと呼ばれます。タイプのサブスクリプトは、subscriptキーワードの前にstaticキーワードを表記します。クラスは代わりにclassキーワードを使用して、サブクラスがそのサブスクリプトのスーパークラスの実装をオーバーライドできるようにすることができます。以下の例は、タイプのサブスクリプトを定義して呼び出す方法を示しています。
// enum のタイプサブスクリプト enum Planet: Int { case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune static subscript(n: Int) -> Planet { return Planet(rawValue: n)! } } let mars = Planet[4] print(mars) // クラス のタイプサブスクリプト class Planet { class subscript(n: Int) -> String { return "subscript class" } } let mars = Planet[4] print(mars)