subscript
는 클래스, 구조체, 열거형 등의 인스턴스에서 컬렉션(Collection)처럼 동작하도록 하기 위해 사용되는 기능이다. 예를 들어, 배열이나 딕셔너리에서 요소에 접근하기 위해 대괄호([]
)를 사용하는 것처럼, 자신만의 타입에서도 이와 같은 동작을 구현할 수 있다.
쉽게 말해, subscript
는 인스턴스 내부 데이터에 간단하게 접근할 수 있도록 하는 특수한 메서드이다.
subscript(index: Int) -> Type {
get {
// 인덱스에 따른 값을 반환
}
set(newValue) {
// 인덱스에 해당하는 값 설정
}
}
struct MyCollection {
private var items = [1, 2, 3, 4, 5]
subscript(index: Int) -> Int {
get {
// index 범위 확인
precondition(index >= 0 && index < items.count, "Index out of range")
return items[index]
}
set(newValue) {
precondition(index >= 0 && index < items.count, "Index out of range")
items[index] = newValue
}
}
}
var collection = MyCollection()
print(collection[2]) // 출력: 3
collection[2] = 99
print(collection[2]) // 출력: 99
struct KeyValueStore {
private var storage: [String: String] = [:]
subscript(key: String) -> String? {
get {
return storage[key]
}
set(newValue) {
storage[key] = newValue
}
}
}
var store = KeyValueStore()
store["name"] = "Alice"
print(store["name"] ?? "Unknown") // 출력: Alice
여러 매개변수 가능
subscript
는 하나 이상의 매개변수를 받을 수 있다.
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)
}
subscript(row: Int, column: Int) -> Double {
get {
precondition(row >= 0 && row < rows && column >= 0 && column < columns, "Index out of range")
return grid[(row * columns) + column]
}
set {
precondition(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] = 5.5
print(matrix[0, 1]) // 출력: 5.5
읽기 전용 subscript
get
만 구현하면 읽기 전용으로 만들 수 있다.
struct ReadOnly {
private var items = [10, 20, 30]
subscript(index: Int) -> Int {
return items[index]
}
}
let readOnly = ReadOnly()
print(readOnly[1]) // 출력: 20
// readOnly[1] = 40 // 오류: 수정 불가
subscript
에 매개변수 이름 생략
아래와 같이 구현하면 더 간결하게 사용할 수 있다.
struct Squared {
subscript(_ number: Int) -> Int {
return number * number
}
}
let squared = Squared()
print(squared[4]) // 출력: 16
subscript
는 대괄호([]
)를 사용해 데이터에 접근하는 기능을 커스터마이징한다.precondition
은 Swift에서 런타임 중 특정 조건을 검사하고, 조건이 만족되지 않을 경우 프로그램을 종료하는 함수이다. 보통 디버깅 목적으로 사용되며, 조건이 반드시 충족되어야 하는 상황을 명확히 하는 데 유용하다.
precondition
의 역할precondition(_ condition: Bool, _ message: @autoclosure () -> String = "")
condition
: 조건을 나타내는 Boolean 값이다. true
이면 정상적으로 실행되고, false
이면 프로그램이 종료된다.message
: 조건이 충족되지 않을 경우 출력되는 메시지이다(선택 사항).let age = 25
precondition(age >= 0, "Age must be non-negative")
print("Age is valid!") // 출력: Age is valid!
let age = -5
precondition(age >= 0, "Age must be non-negative")
// 프로그램 종료, 출력:
// Fatal error: Age must be non-negative
func divide(_ dividend: Int, by divisor: Int) -> Int {
precondition(divisor != 0, "Divisor must not be zero")
return dividend / divisor
}
print(divide(10, by: 2)) // 출력: 5
print(divide(10, by: 0)) // 프로그램 종료, 오류 메시지 출력
func getElement(at index: Int, in array: [Int]) -> Int {
precondition(index >= 0 && index < array.count, "Index out of range")
return array[index]
}
let numbers = [10, 20, 30, 40]
print(getElement(at: 2, in: numbers)) // 출력: 30
print(getElement(at: 5, in: numbers)) // 프로그램 종료, 오류 메시지 출력
func validatePassword(_ password: String) {
precondition(password.count >= 8, "Password must be at least 8 characters")
print("Password is valid")
}
validatePassword("secure123") // 출력: Password is valid
validatePassword("short") // 프로그램 종료, 오류 메시지 출력
precondition
: 조건이 충족되지 않을 경우 프로그램을 종료해 안전성을 확보한다.assert
와는 다르게 프로덕션 환경에서도 동작하므로, 중요한 상황에서 사용된다. Swift에서 assert
는 디버그 빌드(Debug Build) 중 특정 조건이 참인지 확인하고, 조건이 거짓일 경우 프로그램을 종료하며 에러 메시지를 출력하는 디버깅 도구이다.
assert
는 개발 단계에서 코드의 논리적 결함을 발견하는 데 유용하며, 배포 빌드(Release Build)에서는 비활성화되므로 성능에 영향을 미치지 않는다.
assert(_ condition: Bool, _ message: @autoclosure () -> String = "")
condition
: 조건을 나타내는 Bool
값이다. true
이면 아무 일도 하지 않고, false
이면 프로그램이 종료된다.message
: 조건이 거짓일 경우 출력될 에러 메시지(선택 사항)이다.let age = 20
assert(age >= 0, "Age must be a non-negative value")
print("Age is valid!") // 출력: Age is valid!
let age = -5
assert(age >= 0, "Age must be a non-negative value")
// 프로그램 종료, 오류 메시지 출력:
// Assertion failed: Age must be a non-negative value
assert
의 동작 원리true
)이면 아무 일도 하지 않는다.false
)이면 프로그램이 종료된다.assert
코드는 실행되지 않는다.assertionFailure
assertionFailure
는 조건 없이 항상 프로그램을 종료하는 디버깅 도구이다.
func handleUserInput(_ input: String) {
switch input {
case "option1":
print("Option 1 selected")
case "option2":
print("Option 2 selected")
default:
assertionFailure("Unexpected input: \(input)")
}
}
handleUserInput("unknown") // 프로그램 종료, 오류 메시지 출력
// Assertion failed: Unexpected input: unknown
assert
와 precondition
의 차이특징 | assert | precondition |
---|---|---|
활성화 조건 | 디버그 빌드(Debug Build)에서만 활성화 | 배포 빌드(Release Build)에서도 활성화 |
사용 목적 | 개발 중 논리적 결함 확인 | 반드시 충족되어야 하는 런타임 조건 확인 |
배포 빌드에서 동작 여부 | 동작하지 않음 | 동작함 |
사용 예 | 테스트 중 임시 조건 검증 | 중요한 런타임 안전성 보장 |
assert
사용 시기:
precondition
사용 시기:
assert
사용func divide(_ dividend: Int, by divisor: Int) -> Int {
assert(divisor != 0, "Divisor must not be zero")
return dividend / divisor
}
print(divide(10, by: 2)) // 출력: 5
print(divide(10, by: 0)) // 프로그램 종료, 오류 메시지 출력
// Assertion failed: Divisor must not be zero
let playerLives = -1
assert(playerLives >= 0, "Player lives cannot be negative")
// Assertion failed: Player lives cannot be negative
assert
: 디버깅 단계에서 조건을 확인하고, 조건이 거짓일 경우 프로그램을 종료한다.