먼저 이글을 보기전 클래스와 구조체, 프로퍼티 게시글을 안봤다면 이해하기 어려울 수 있다 (보고오자)
서브스크립트라는 키워드가 조금 생소할 수 있다 하지만 우리는 이미 서브스크립트를 알고 있다.
이전까지는 배열이나 딕셔너리에서 제공하는 서브스크립트만 사용이 가능했다면 이제부턴 이 서브스크립트를 직접 구현해서 사용할 수 있다!
서브 스크립트를 사용하면 인스턴스 이름 뒤에 대괄호에 하나 이상의 값을 작성하여 타입의 인스턴스를 조회할 수 있다.
(인스턴스 메서드 구문과 계산된 프로퍼티 구문과 유사함)
형태는 이전에 작성한 프로퍼티와 굉장히 유사한 형태를 갖는다.
get과 set을 가지며, 구조체나 클래스 내부에 작성한다.
struct TimesTable {
let multiplier: Int
subscript(index: Int) -> Int {
return multiplier * index
}
}
let threeTimesTable = TimesTable(multiplier: 3)
print(threeTimesTable[6])
// 결과.....18
↳ 형태는 다음과 같으며, 위 서브스크립트는 읽기전용 서브스크립트이다.
subscript(index: Int) -> Int {
get {
// Return an appropriate subscript value here.
}
set(newValue) {
// Perform a suitable setting action here.
}
}
↳ get과 set을 갖는 서브스크립트
subscript(index: Int) -> Int {
//Code here...
}
↳ 프로퍼티와 유사하게 get전용(읽기 전용)으로 만들수도 있다.
서브스크립트는 프로퍼티와도 비슷하지만 함수와도 굉장히 비슷하다.
- 함수처럼 파라메터를 받고 반환을 한다
- 가변 파라메터를 지원한다.
- 파라메터 기본값을 지정 가능하다.
- 여러개의 파라메터를 받아올 수 있다.
- 상속이(오버라이드) 가능하다.
- 오버로드가 가능하다
struct StringConnector {
subscript(strings: String...) -> String {
return strings.joined(separator: " ")
}
}
let connect = StringConnector()
print(connect["Swift", "는", "재미있는", "언어입니다."])
// 출력: Swift 는 재미있는 언어입니다.
↳ 다음과 같이 함수와 같은 형태로 가변 파라메터를 지원한다.
그냥 []안에 아무것도 작성하지 않아도 동작하는 서브스크립트를 만들 수 있다는 말이다.
struct StringConnector {
subscript(strings: String...) -> String
{
return strings.joined(separator: " ")
}
subscript() -> String
{
return "아무것도 없었다..."
}
}
let connect = StringConnector()
print(connect[])
// 출력: 아무것도 없었다...
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
}
}
}
//행렬 생성
var matrix = Matrix(rows: 2, columns: 2)
//행렬 좌표에 값 입력
matrix[0, 1] = 1.5
matrix[1, 0] = 3.2
↳ 여기서 assert()는 if나 guard같이 유효성을 검사해주는 함수이다, 그냥 false값이 들어오면 에러메시지를 출력한다.
(생성된 행렬에 맞는 좌표값이 입력되는지 확인하기 위해서 작성되었다.)
struct StringConnector {
subscript(strings: String...) -> String
{
return strings.joined(separator: " ")
}
subscript() -> String
{
return "아무것도 없었다..."
}
}
let connect = StringConnector()
print(connect[])
// 출력: 아무것도 없었다...
↳ 오버로드란 앞서 파라메터 기본값에서 설명한대로 파라메터를 다르게 해서 여러개의 서브스크립트를 생성하는 것을 말한다.
서브스크립트는 상속을 지원하기에 당연하게도 오버라이드또한 지원한다.
class ParentClass {
subscript(index: Int) -> Int {
return index * 2
}
}
class ChildClass: ParentClass {
override subscript(index: Int) -> Int {
return super[index] + 1
}
}
let parent = ParentClass()
print(parent[5]) // 출력: 10
let child = ChildClass()
print(child[5]) // 출력: 11
↳ 오버라이드를 하는 경우 override키워드를 서브스크립트 앞에 붙여줘서 명시해줘야 한다.
서브스크립트는 static키워드를 이용한 사용을 지원한다.
struct TemperatureConverter {
static subscript(fahrenheit fahrenheit: Double) -> Double {
return (fahrenheit - 32) * 5 / 9
}
static subscript(celsius celsius: Double) -> Double {
return (celsius * 9 / 5) + 32
}
}
// 화씨를 섭씨로 변환
let celsius = TemperatureConverter[fahrenheit: 98.6]
print("섭씨 온도: \(celsius)") // 출력: 섭씨 온도: 37.0
// 섭씨를 화씨로 변환
let fahrenheit = TemperatureConverter[celsius: 37.0]
print("화씨 온도: \(fahrenheit)") // 출력: 화씨 온도: 98.6
↳ 이렇게 인스턴스의 생성없이도 서브스크립트를 사용할 수 있다.
- 서브스크립트는 구조체, 클래스, 열거형 내부에 작성된다.
- 형태는 프로퍼티와 함수와 굉장히 유사하다
- 오버로드나 오버라이드를 지원한다.
- 타입 서브스크립트또한 존재한다.