[Swift] Swift 5.6 의 Existential any
개-하!!! 다들 Swift 5.6 Release 된거 알구 현생 살고 계시는쥐!?!!
저는 물론 몰랐다가 오늘 알았기 때문에,, ◠‿◠ 스윽 보다가 알아두면 좋을 것 같은 내용인 “SE-0335 — Introduces existential any
" 를 들고 돌아왔습니다
아 뭔지 앎 ㅅㄱ! 하시는 분들은 뒤로 가기를 누르는 것으로하고,,,,,,,,!!!
아직 남아 계신 분들은,, 혹시 existential type 이 뭔지 아시나요??
바로 protocol 이 type 으로 사용될 때, 해당 type을 “existential type” 라고 합니다
무슨 말인지 코드를 보면 바로 이해갈텐데요,
protocol P {}
protocol Q {}
struct S: P, Q {}
let p1: P = S() // 해당 맥락에서 'P' 는 existential type
위에서 protocol P
가 p1
의 type 으로 사용되었으므로, 이 맥락에서 P
는 existential type 입니다.
어떤 concrete type 이든 상관 없이 해당 protocol 을 conform 하면 모두 existential type 에 할당될 수 있져 ㅇㅇ (+ 추상화 쌉 파서블!)
뭔 말인지는 예시로 설명을 이어가볼게요!
protocol P {}
struct S: P {}
class C: P {}
var p1: P = S() // ㅇㅋ
p1 = C() // ㅇㅋ
S
와 C
라는 두개의 concrete type 모두 protocol P
를 conform 하고 있기 때문에 p1
변수에 들어갈 수 있슴다
🤷🏻♀️ : 아 rgrg~~ 나 이렇게 평소에 잘 써왔는데 existential type 이라는 용어가 걍 생소했을 뿐임~ protocol 이 type 으로 사용되는 맥락에서는 existential type 이라고 한다고?? ㅇㅋㅇㅋ!
근데 여러분,,, 아래 코드를 한번 볼게요. 뭐가 concrete type 이고 뭐가 existential type 인지 구분 가능한가여??
var foo: Foo
var bar: Bar
하나 더 보겠습니다. Vehicle
이 concrete type 인지 existential type 인지 구분이 가나요??
func travel(using vehicle: Vehicle) { }
마지막으로 하나 더! ConcreteP
라는 Generic 이 P
라는 protocol conform 이 필요한건지, class inherit 가 필요한건지 구분이 가시나요?
func generic<ConcreteP: P>(p: ConcreteP) { }
여기까지 혼란스러우셨다면,,?! 삐빅 정상입니다.
concrete type 이든 existential type 이든 선언되는 방식이 동일해서 지금 뭐가 뭔지 알 수 없는 상황이죠 ㅇㅇ!
🤷🏻♀️ : 아니 내 잘못임??? Swift 가 애초에 구분 안가게 만들어놨구만 어쩌라고~~~~
맞아요. 우리 잘못은 아니지만,,,! 어쨌든 이런 특성은 개발자들의 혼란을 야기해왔고 종종 코드를 다시 작성해야 하는 경우까지도 발생했다고 합니다.
또한 existential type 은 concrete type 보다 더 많은 비용이 듭니다. existential type 안에는 (protocol conform만 한다면) 값의 type 이 동적으로 변경될 수 있기 때문이죠! 이는 dynamic memory 가 필요함을 의미하고, heap 할당과 reference counting 까지 더해져 existential type 을 사용하는 코드에서는 pointer indirection 와 dynamic method dispatch 가 발생합니다.
이렇게 existential type 을 사용할 때는 concrete type보다 더 많은 비용이 요구됨에도 불구하고, 지금까지 개발자에게 이 퍼포먼스 비용을 나타내는 명확한 구분은 없었습니다.
🤷🏻♀️ : 흠 그래서 어쩌자고??
: 이제 existential types 에 명시적으로 any
를 붙여서 명확히 구분시킬거임!!!!!!!!!!!!!!!!!!!!!!!
좋아여 등장 배경만 알았으면 머,, 오늘 내용은 다 끝났다고 생각하구요,,? ㅋㅎ
이제 Swift 5.6 부터 existential type 앞에 any
키워드가 붙을 수 있어요!
protocol P {}
protocol Q {}
struct S: P, Q {}let p: any P = S()
let pq: any P & Q = S()protocol Vehicle {}
func travel(using vehicle: any Vehicle) { }
앞에 내용이 길었던거치고 실제 코드는,, 뭐 별거 없죠?
추가로 메타타입 관련 변경 사항은 아래와 같습니다
- existential metatype (protocol을 inherit 하고 있는 타입의 메타 타입) :
P.Type
->any P.Type
- protocol metatype :
P.Protocol
->(any P).Type
- protocol metatype value :
P.self
->(any P).self
전 / 후 코드를 비교해보져
protocol P {}
struct S: P {}// 전
let existentialMetatype: P.Type = S.self
let protcolMetatype: P.Protocol = P.self// 후
let existentialMetatype: any P.Type = S.self
let protcolMetatype: (any P).Type = (any P).self
ㅇㅋㅇㅋ??
Swift 5.6 에서는 any
키워드를 이용해서 명시적으로 existential type 을 선언할 수 있다~ 정도지만, 추후 버전에서는 any
를 명시 하지 않으면 warning이 뜨고, Swift 6 부터는 error 를 띄울 계획이라고 합니다
그러니까 나중에 error 떠서 고치는 부분을 한 곳이라도 줄이려면 지금부터 any
키워드를 사용해서 existential type 을 선언하는 습관을 들여야겠네요 ㅎ ㅠ
오늘은 여기까지 알아보는걸로!! 그럼 20000!!!