본문 바로가기

iOS/Swift

Swift) Metatype(.self, .Type, .Protocol) 정복하기 (2/2)

 

 

안녕하세요 :) 소들입니당!!!

연휴에 쓰는 두번째 포스팅.. 낄낄

연휴엔 공부해야 제맛 아니겠읍니까

 

뭐 쨌든

이전 포스팅에서 .self .Type에 대해서 공부 했었어요!

바로 "메타타입" 이란 것과 관련이 있었죠 

이번엔 .Protocol이란 것과 self와 .selfSelf의 차이점에 대해서 알아보려고 합니당!!

이전 포스팅을 잘 이해했다면 어렵지 않을 거 같아요

모든 포스팅은 편의 말투로 합니다~!!

 

 

 

 

1. .Protocol : 프로토콜의 메타타입은 조금 다릅니다..

 

자 우리가 다음과 같이 Human이란 프로토콜을 만들었을 때 

 

 

protocol Human { }
 
let humanType: Human.Type = Human.self      // Cannot convert value of type 'Human.Protocol.Type' to specified type 'Human.Type'

 

 

이 프로토콜의 메타타입을 얻기 위해

Human.Type이란 타입의 변수 humanType을 만들고

Human.self를 넣어주면 에러가 발생함

 

왜냐??

Human.self가 틀린 것이 아님!!

Human이란 프로토콜의 메타타입 값을 갖고오기 위해 Human.self라고 해주는 것까지는 좋았음!

 

근데 문제는 바로 humanType의 타입, 즉 Human.Type에 있음

우리가 Type Annotation으로 humanType의 타입은 Human.Type이라고 정의를 해버렸잖음?

근데 사실 Human.self로 얻는 프로토콜 자체의 메타타입은 저렇게 정의되지 않음!!

 

자,,, 지금껏 어려운 말로 설명해서 이해가 안 가겠지만

다음 예제를 보면 이해할 수 있음

 

 

struct SodeulHuman { }
let sodeulType: Human.Type = Sodeul.self       // Sodeul.Type

 

 

이렇게 할 경우 에러가 안 나거든

무슨 말이냐?

 

Human.Type을 할 경우,

Human이란 프로토콜의 메타 타입을 얘기하는 것이 아니라,

해당 프로토콜을 따르는 Sodeul의 메타타입을 얘기하는 것이 되어버림

(이를 existential metatype 이라 부른다고 함!)

 

따라서 만약 나는 진짜 Human이란 프로토콜의 메타타입을  얻고 싶다?

하면 사용하는 것이 바로

 

.Protocol

 

이라는 키워드임!!

 

 

protocol Human { }
 
let humanType: Human.Protocol = Human.self      // Human.Protocol

 

 

따라서 이렇게 .Protocol을 이용하면, 

프로토콜의 메타타입을 얻을 수 있음

 

사실 Type Annotation을 생략하고  type(of:)메소드를 통해서 봐도

 

 

 

 

뒤에 메타타입이 하나 더 붙긴하지만,

Human 프로토콜의 메타타입은 .Protocol이 들어가야 한단 것을 알 수 있음!!!

 

근데 실제로 .Protocol을 사용하는 일은 현업에서 거의 없을 것이기 때문에..

아마 볼 일이 없을 거라 함.. ㅃ...ㅏ..이..

 

 

 

 

2. self와 .self와 Self의 차이

 

자 마지막으로 헷갈리기 쉬운

 

self

.self

Self

 

의 차이점에 대해 알아보도록 합시당 :)

분명 같은 self들인데 셋의 쓰임새는 완전 다르단 말이죠??

어렵지 않으니 대충 알아봐봅시당 

 

 

 

2-1. self

 

self란 것은 인스턴스에서 생성되며, 해당 인스턴스에 대해서 나타낸다

 

넹 여러분이 당연하게 써왔던 클래스, 구조체 만들 때

 

 

class Human {
    var name = "Sodeul"
    
    func printName() {
        print(self.name)
    }
}

 

 

이 때 사용하는 것이 바로 self란 것임!!

뭐 모르지 않을 거라 생각합니당

 

 

 

2-2. .self

 

.self는 우리가 이전 포스팅에서 배웠잖음!?!?

 

 

let tableView = UITableView()
tableView.register(SodeulCell.self, forReuseIdentifier: "SodeulCell")

 

 

해당 타입의 메타타입 값을 얻기 위할 때 사용한단 것을! :)

 

 

 

2-3. Self

 

자 그럼 마지막, 대문자 Self에 대해 알아보겠음

 

Self란 하나의 Type으로, 현재 속한 코드의 Type이 Self의 Type이 된다

 

응 먼서리야

예제를 보면 쉬움

 

 

extension Int {
    static let zero: Int = 0
    func makeZero() -> Int {
        return Int()
    }
}

 

 

자 우리가 위와 같이 Int형을 확장하려고 할 때,

물론 위처럼 프로퍼티 zero의 타입, 메서드 makeZero의 반환 타입을 직접 Int로 명시해도 됨!!!

그러나 뭐라고??

Self는 현재 속한 코드의 타입의 Self의 타입이 된다구!

현재 내 타입이 Int이기 때문에, Self의 타입또한 Int가 되고

 

 

extension Int {
    static let zero: Self = 0
    func makeZero() -> Self {
        return Self()
    }
}

 

 

이렇게 Int라는 타입 대신 Self를 쓸 수 있는 것임!!

 

그럼 Self를 쓸 때의 장점이 무엇이냐,

타입에 의존하지 않는 코드가 될 수 있음

또한 나중에 프로토콜 정리할 때쯤 다시 쓸거 같긴 한데

프로토콜 내에서 실제 타입 대신해서 사용하기도 함

(이 경우, Self 타입은 프로토콜을 채택해서 구현하는 실제 타입으로 추론됨)

 

 

이제 같은 self 지만

앞에 .이 있느냐 없느냐/소문자냐 대문자냐에 따라 쓰임새가 다르단 걸 다 이해 했길 :)

 

 

 

 

 

.

.

.

 

오늘은 Metatype에 대해 2편!!!

.Protocol에대해 알아보고, 실제 개발할 때 헷갈릴 수 있는 self에 대해 정리 해봤어요!

음... 사실 1번 포스팅에서 의문을 많이 놓고 끝냈기 떄문에

그거에 대해 알게되면 포스팅을 더 보충하도록 하겠습니당

 

오타지적 및 잘못된 내용 피드백 대환영!! :)

읽어주셔서 감사합니다.



Calendar
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
최근 댓글
Visits
Today
Yesterday