Swiftのsubscriptsは、配列や辞書のようにインデックスを使ってコレクション、コンテナ、またはユーザー定義型の要素にアクセスするための便利な構文を提供します。これらは、独自のクラス、構造体、および列挙型内で宣言およびオーバーライドすることができます。
subscriptsは、オブジェクトへのインデックスアクセスを統一する手段としてSwiftに登場し、コレクションから始まり、その後任意のユーザー定義型に広がりました。主な目的は、表現力と可読性を向上させ、データアクセスメソッドを配列の操作に似た「自然な」構文に変えることです。
他の言語(例えば、Java)では、構造要素へのアクセスはget/setメソッドを使用して行われるため、コードが冗長になります。可読性の向上とデータアクセスの容易さを求める中でsubscriptsが生まれました。Swiftでは、安全なアクセス、ゲッターとセッター、可能なエラーおよびoptionalな戻り値に特別な注意が必要です。
Subscriptは、任意のクラス、構造体、列挙型でsubscriptキーワードを使用して宣言できます。また、パラメータや戻り値の型に応じた複数のオーバーロードをサポートしています。
カスタムsubscriptの例:
struct Matrix { let rows: Int, columns: Int private var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } subscript(row: Int, column: Int) -> Double { get { precondition(row >= 0 && row < rows) precondition(column >= 0 && column < columns) return grid[(row * columns) + column] } set { precondition(row >= 0 && row < rows) precondition(column >= 0 && column < columns) grid[(row * columns) + column] = newValue } } } var matrix = Matrix(rows: 2, columns: 2) matrix[1, 1] = 3.14 print(matrix[1, 1]) // 3.14
主な特徴:
ゲッターなしでsubscriptを宣言できますか?
はい。読み取り専用のsubscriptが必要な場合は、getのみを実装すれば十分です。
struct ReadOnlyArray { private let items = [1, 2, 3] subscript(index: Int) -> Int { get { return items[index] } } }
異なるシグネチャを持つ複数のsubscriptを同じ型で宣言できますか?
はい、subscriptはパラメータの数と型に基づいてオーバーロードできます。
struct Collection { subscript(index: Int) -> String { ... } subscript(key: String) -> Int? { ... } }
プロトコルでsubscriptを宣言し、構造体/クラスで実装することは可能ですか?
はい、プロトコルはsubscriptの実装を要求することができ、具体的な型はそれを実装する必要があります。
protocol MySubscriptable { subscript(index: Int) -> String { get set } } struct SubData: MySubscriptable { private var items = ["a", "b"] subscript(index: Int) -> String { get { return items[index] } set { items[index] = newValue } } }
開発者が範囲チェックなしでsubscriptを実装しました。その結果、存在しないインデックスにアクセスしようとすると、アプリケーションはランタイムエラーでクラッシュしました。
利点: コードが簡潔になりました。
欠点: アプリケーションが突然のエラーでクラッシュするようになりました。
preconditionを持ち、optionalを返すかエラーをスローする可能性のあるsubscriptの実装。
利点: コードはユーザーにとって安全になり、エラーを処理できます。
欠点: エラー処理のために追加のロジックを組み込む必要があり、無効なインデックスに対する動作を考慮する必要があります。