-
[Swift] some & any야매 iOS 2023. 8. 7. 07:00
some은 Swift 5.1 그리고 any는 Swift 5.6에서 생성된 키워드
두 키워드는 protocol과 함께 주로 사용한다.
두 키워드의 탄생으로 인해
protocol can only be used as generic constraint because it has Self or associated type requirements에러로부터 자유로워 졌다.some
some 키워드는 무언가가 프로토콜을 준수한다는 것을 표현하는 opaque 타입을 생성한다.
opaque type
opaque 타입은 객체 또는 값이 어떤 프로토콜을 준수한다고 할 때 실제로 해당 객체 또는 값의 타입을 감춘다.
protocol Person { let name: String { get } associatedType Job func describe(with job: Job) } struct Someone: Person { let name: String = "someone" func describe(with job: Doctor) { print("name = \\(name), job = \\(job.name)") } } struct Anyone: Person { let name: String = "anyone" func describe(with job: Player) { print("name = \\(name), job = \\(job.name)") } } struct Doctor { let name: String } struct Player { let name: String } var person: some Person = Someone()위 예시를 보면 person 변수에 Someone의 인스턴스를 생성해 할당했다.
→ 타입이 some Person이기 때문에 Person 프로토콜을 준수하는 무언가를 person에 할당할 수 있게 된다.
적용
함수 매개변수
func work(_ person: some Person) { } func work<T: Person>(_ person: T) { } func work<T>(_ person: T) where T: Person { }새로운 기능이라기보단 기존 기능을 대체하는 느낌
변수
변수에 some 키워드를 사용하면 컴파일러는 할당받은 객체 또는 값의 타입으로 인식한다
// 컴파일러는 person은 Someone 타입으로 인식한다 var person: some Person = Someone() // 컴파일 에러 발생 person = AnyOne() // 컴파일 에러 발생 let people: [some Person] = [ Someone(), Anyone(), Someone() ] let people: [some Person] = [ Someone(), Someone(), Someone() ]하지만 유의해야 되는 점은 some 키워드에 같은 타입의 값을 할당해도 에러가 난다는 것이다.
var person: some Person = Someone() // 에러 발생 person = Someone()이유는 정확하게 모르겠지만 예상하자면 some 키워드는 컴파일러가 처음 할당받은 객체 또는 값의 타입으로 인식하지만 syntax 상으로 opaque 타입이기 때문에 현재 저장된 타입의 명확한 타입을 알 수 없어 할당하지 못하는 것이 아닐까라는 생각이 든다.
반환값
변수와 마찬가지로 some 키워드는 타입을 하나의 타입으로 규정짓기 때문에 하나의 함수/메서드 내에서 다른 타입을 반환할 수 없다.
// 컴파일 에러 func craetePerson() -> some Person { if true { return Someone() } return AnyOne() }
any
any 키워드는 existential type을 생성한다.
existential type
existential 타입은 특정 프로토콜을 준수하는 무언가를 가진 박스를 의미한다.
특징
some과 다르게 box이기 프로토콜을 준수하는 모든 것을 담을 수 있다.
var person: Person = Someone() var person: any Person = Somone()사실 현재 사용하는 방식과 크게 다르지 않다.
Why use some & any
이전에는 변수, 반환값, 매개변수에 프로토콜 타입을 사용할 때 any 또는 some 키워드를 붙일 필요 없이 사용할 수 있었다. 하지만 왜 이런 키워드를 만들었을까나?
프로토콜을 타입으로 지정하고 해당 변수, 매개변수에 해당 값을 할당했을 때 타입은 런타임에 결정된다.
런타임에 결정되는 것은 성능적으로 악영향을 미친다.
- 런타임에 결정되므로 얼마나 많은 메모리를 사용해야 하는지 컴파일 타임에 알 수 없다.
- dynamic dispatch를 통해 concrete 타입에 접근하므로 static dispatch 보다 느리다.
타입이 명확한 경우에는 some을 붙여 dynamic이 아닌 static하게 접근해 성능을 높이려는 것이 목적인 것 같다.
정리
장난감
- 인형
- 레고
- 보드게임
// toy 변수는 레고 박스가 됨 그러므로 다른 장난감을 담을 수 없음 var toy: some 장난감 = 레고() // toy 변수는 장난감 박스이므로 그 안에 레고, 인형, 보드게임 모두 넣을 수 있음 var toy: any 장난감 = 레고()'야매 iOS' 카테고리의 다른 글
[iOS/Swift] SwiftUI 계산기 (0) 2023.08.07 [iOS] Certificate & Provisioning (0) 2023.08.07 [Swift] Protocol Oriented Programming (0) 2023.08.07 [iOS/Swift] @StateObject vs @ObservedObject (0) 2023.08.07 [iOS/Swift] Operation (0) 2023.08.06