반응형
Swift는 강력한 문법적 유연성을 제공하는 언어로, 오퍼레이터 오버로딩(operator overloading)과 첨자 표기법(subscript) 외에도 여러 기능을 활용하면 더욱 직관적이고 읽기 쉬운 코드를 작성할 수 있습니다. 이 글에서는 이러한 기능을 활용하여 사용자 정의 타입을 설계하는 방법을 자세히 설명하겠습니다.
1. 오퍼레이터 오버로딩
오퍼레이터 오버로딩
Swift에서는 기존의 연산자(+, -, *, /, == 등)를 사용자 정의 타입에서 재정의할 수 있습니다. 이를 오퍼레이터 오버로딩이라고 하며, 이를 활용하면 연산을 더욱 직관적으로 표현할 수 있습니다.
오퍼레이터 오버로딩의 장점
- 코드 가독성 향상: 수학적인 개념을 코드에 직접 적용할 수 있음
- 유지보수성 증가: 별도의 메서드를 정의하지 않고 연산자만으로 표현 가능
- 객체 간 연산 표현 가능: 사용자 정의 타입에서도 기본 타입처럼 연산 가능
예제: 2D 벡터 연산 구현
import Foundation
struct Vector2D {
var x: Double
var y: Double
// 벡터 덧셈 연산자 오버로딩
static func + (lhs: Vector2D, rhs: Vector2D) -> Vector2D {
return Vector2D(x: lhs.x + rhs.x, y: lhs.y + rhs.y)
}
// 벡터 뺄셈 연산자 오버로딩
static func - (lhs: Vector2D, rhs: Vector2D) -> Vector2D {
return Vector2D(x: lhs.x - rhs.x, y: lhs.y - rhs.y)
}
// 벡터 스칼라 곱 연산자 오버로딩
static func * (lhs: Vector2D, scalar: Double) -> Vector2D {
return Vector2D(x: lhs.x * scalar, y: lhs.y * scalar)
}
// 벡터 크기 비교 연산자 오버로딩
static func == (lhs: Vector2D, rhs: Vector2D) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
}
let v1 = Vector2D(x: 3, y: 4)
let v2 = Vector2D(x: 1, y: 2)
let sum = v1 + v2 // Vector2D(x: 4, y: 6)
let diff = v1 - v2 // Vector2D(x: 2, y: 2)
let scaled = v1 * 2 // Vector2D(x: 6, y: 8)
print(sum, diff, scaled)
연산자 오버로딩을 적용한 벡터 연산 다이어그램
2. 첨자 표기법을 활용한 사용자 정의 컬렉션 구현
첨자 표기법(subscript)
Swift에서는 subscript 키워드를 사용하여 객체를 배열처럼 인덱스를 이용해 접근할 수 있도록 만들 수 있습니다. 이를 이용하면 사용자 정의 컬렉션 타입을 보다 직관적으로 설계할 수 있습니다.
예제: 사용자 정의 행렬(Matrix) 타입
struct Matrix {
private var data: [[Double]]
init(rows: Int, columns: Int, defaultValue: Double = 0.0) {
self.data = Array(repeating: Array(repeating: defaultValue, count: columns), count: rows)
}
var rowCount: Int { data.count }
var columnCount: Int { data.first?.count ?? 0 }
// 행렬의 원소에 접근하는 첨자 표기법 구현
subscript(row: Int, col: Int) -> Double {
get {
precondition(row >= 0 && row < rowCount && col >= 0 && col < columnCount, "Index out of range")
return data[row][col]
}
set {
precondition(row >= 0 && row < rowCount && col >= 0 && col < columnCount, "Index out of range")
data[row][col] = newValue
}
}
}
var matrix = Matrix(rows: 3, columns: 3)
matrix[1, 1] = 5.5
print(matrix[1, 1]) // 5.5
3. 기타 Swift의 강력한 문법 기능
프로퍼티 래퍼(Property Wrappers)
Swift의 @propertyWrapper를 활용하면 변수의 동작을 캡슐화할 수 있습니다.
@propertyWrapper
struct Uppercase {
private var value: String = ""
var wrappedValue: String {
get { value }
set { value = newValue.uppercased() }
}
}
struct User {
@Uppercase var name: String
}
var user = User(name: "john")
print(user.name) // "JOHN"
키 경로(KeyPath)
키 경로를 활용하면 객체 속성을 더 유연하게 다룰 수 있습니다.
struct Person {
let name: String
let age: Int
}
let person = Person(name: "Alice", age: 25)
let nameKeyPath = \Person.name
print(person[keyPath: nameKeyPath]) // "Alice"
반응형
'프로그래밍언어' 카테고리의 다른 글
[Swift] Actor와 Structured Concurrency (0) | 2025.02.16 |
---|---|
[Swift] Distributed Actor (0) | 2025.02.16 |
[Swift] Swift의 DSL(Domain-Specific-Language) 설계 및 구현 (0) | 2025.02.16 |
[Swift] Mirror 타입 (0) | 2025.02.16 |
[Swift] Swift Reflection과 런타임 프로그래밍 (0) | 2025.02.16 |