Swift의 서브스크립트 메커니즘은 2014년에 언어와 함께 등장했으며, 컬렉션 데이터에 보다 편리한 구문으로 접근하기 위해 설계되었습니다. 서브스크립트를 통해 배열, 딕셔너리 및 기타 컬렉션의 요소에 대괄호를 통해 접근할 수 있습니다. 현대의 Swift는 사용자 정의 타입을 위한 사용자 정의 서브스크립트를 만들 수 있도록 하여 표준 데이터 구조처럼 API를 직관적으로 만듭니다.
문제: 이전에는 접근 방법이 더 번거롭게 보였으며 (예: .getElement(at:)), 서브스크립트는 타입과의 상호작용을 간결하게 만들어줍니다. 그러나 잘못된 구현은 비효율적인 코드나 컬렉션 범위를 초과하는 접근 오류를 일으킬 수 있습니다.
해결책: 서브스크립트를 구현하려면 서브스크립트라는 키워드를 사용하고, 그 다음에 매개변수와 반환 값을 지정합니다. 서브스크립트는 읽기 전용일 수도 있고, 읽기 및 쓰기가 가능할 수도 있습니다. 또한, 서브스크립트는 다른 매개변수에 대해 오버로딩 될 수 있습니다.
코드 예:
struct Matrix { let rows: Int let columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns self.grid = Array(repeating: 0.0, count: rows * columns) } subscript(row: Int, column: Int) -> Double { get { assert(row >= 0 && row < rows && column >= 0 && column < columns, "Index out of range") return grid[(row * columns) + column] } set { assert(row >= 0 && row < rows && column >= 0 && column < columns, "Index out of range") grid[(row * columns) + column] = newValue } } } var matrix = Matrix(rows: 2, columns: 2) matrix[0, 1] = 3.14 print(matrix[0, 1]) // 3.14
주요 특징:
서브스크립트를 읽기 전용으로만 지정할 수 있나요? 아니면 서브스크립트는 항상 get과 set을 가져야 합니까?
서브스크립트는 구현에 set이 없는 경우 읽기 전용(오직 get만)일 수 있습니다. 두 가지 접근자를 모두 구현할 필요는 없으며, 이는 속성과 유사합니다.
코드 예:
subscript(index: Int) -> Int { get { return index * 2 } }
서브스크립트에 inout을 통해 변경 가능한 매개변수를 전달할 수 있나요?
아니요, 서브스크립트는 시그니처에서 inout 매개변수를 지원하지 않습니다. 모든 서브스크립트 매개변수는 accessor 본문 내에서 let 상수로 처리됩니다.
서브스크립트가 선택적 타입을 반환할 수 있나요?
네, 서브스크립트는 선택적 값을 반환할 수 있으며, 이는 배열의 범위를 초과할 위험 없이 컬렉션 요소에 안전하게 접근하는 데 유용합니다.
코드 예:
extension Array { subscript(safe index: Int) -> Element? { return indices.contains(index) ? self[index] : nil } }
입력 인덱스 오류로 인해 앱이 충돌하도록 하는 복합 타입 행렬에 대한 서브스크립트 구현은 범위 초과에 대한 유효성 검사가 없습니다.
장점:
단점:
안전한 인덱싱 및 오류 처리를 위한 선택적 서브스크립트를 추가하여 API를 명확하고 안전하게 만듭니다.
장점:
단점: