티스토리 뷰

iOS/Swift-Memo

MetaType, self 와 Self

malrang-malrang 2022. 4. 29. 19:03

MetaType, self 와 Self

MetaType

공식문에서는 Metatype 은 타입의 타입이라고 정의 되어있다.
이게 대체 무슨소리일까..

아래 예시를 보자

struct Person {
   static let name = "malrang"
   var age = 29
}

let malrang = Person()

지금껏 나는 Person 이라는 타입을 정의한후
Person 타입의 malrang 이라는 상수를 정의해주었다.
malrangPerson 타입의 인스턴스다.
하지만 여기서 Person 은 타입의 타입인 메타타입이라 한다.

malrang 인스턴스의 타입의 타입
그러니까 즉 타입 자체?본체?를 메타타입이라고한다.

type(of:)

요 메서드는 파라미터에 인스턴스를 넣게되면 인스턴스의 메타타입을 반환한다.
아래 예시를보자

let malrang = Person()
let malrangType = type(of: malrang) // Person.Type 
malrangType.name                    // malrang

type(of:) 를 사용해서 malrangType 이라는 애한테 Person 타입을 할당해줬다. 인스턴스를 넘겨준게 아니라 타입 자체를, 메타타입을 넘겨준거다.
그렇다면 malrangTypePerson 타입의 타입 프로퍼티인 name 에 접근이 가능해진다!
그리고 malrangType 은 인스턴스가 아니기때문에 age 에는 접근이 불가능하다!!

정리해보자

Person 타입은 Person 타입으로 생성한 인스턴스를 말하며 인스턴스 멤버를 사용가능하다!
Person 타입의 타입(메타타입)은 Person 타입 그자체를 가르키는 타입으로 타입 멤버 사용이 가능하다!

MetaType 을 나타내는 키워드 .Type

위의 예시에서 메타타입을 설명했다.
메타타입인지 아닌지 나타낼수있는 키워드 또한 존재하는데 키워드는 .Type이다.
위의 예시코드에서 타입어노테이션을 작성한다면 아래와 같은 모습이된다.

struct Person {
   static let name = "malrang"
   var age = 29
}

let malrang = Person()
let malrangType: Person.Type = type(of: malrang)
malrangType.name

malrangType 의 타입은 Person.Type 로 명시해주었다.

Protocol 의 MetaType 을 나타내는 키워드 .Protocol

위의 예시에서 struct, class 같은 경우 메타타입을 나타내는 키워드는 .Type 이었지만 프로토콜에서의 메타타입을 나타내는 키워드는 .Protocol 이다.
아래예시 처럼 사용할수 있겠다.

protocol Person { }

let malrangType: Person.Protocol = Person.self

self 와 Self

소문자 self 랑 대문자 Self 두개 다른거다 같은거아니다!!

self(소문자)

self 는 인스턴스에서 생성되며 해당 인스턴스를 나타낸다.

struct Person {
   var age = 29
   func printAge() {
       print(self.age)
   }
}

let malrang = Person()
malrang.printAge()

위의 예시에서 볼수있듯이 printAge() 메서드는 인스턴스 자기자신의 나이를 출력하는 메서드다.
printAge() 내부의 self 는 자기자신을 가르키게 되는것이다.
age 의 값이 29 가 아니고 다른값으로 변하게 되더라도 변한 값을 출력하게 될것이다.
사실 위의 예시 코드에서 self 가 없어도 되지만 명확성을 부여하기 위해 사용된다

해당 타입의 메타타입 값을 얻기위해 사용된다.

struct Person {
    static let name = "malrang"
    var age = 29
    func printAge() {
        print(self.age)
    }
}
let malrang = Person.self

위에서 사용된 type(of:) 메서드 처럼 상수에 타입이름과 self 키워드를 사용해서 메타타입 을 할당해줄수있다.

하지만 type(of:) 를 이용한 방법과 self 를 이용한 방법에는 차이점이 있다.

Static Metatype, Dynamic Metatype

self 를 이용해 만든 메타타입은 Static Metatype 이고
type(of:) 를 이용해 만든 메타타입은 Dynamic Metatype 이다.

둘의 차이점은 타입이 정해지는 시점이 다르다.
Static Metatype 은 컴파일 시점에 타입이 정해진다.
Dynamic Metatype 은 런타임 시점에 타입이 정해진다.

Self(대문자)

Self 는 상황에따라 의미가 다르다.
구조체와 프로토콜을 예시로 들어보겠다.

구조체의 경우
현재 속한 코드의 TypeSelfType 이 된다.

extension String {
   func makeEmpty() -> String {
       return String()
   }
}

String 을 확장해서 makeEmpty() 메서드를 정의해주었다.
반환값은 String 이다.
여기서 Self 를 사용할수도있다. 위의 설명에서 현재 속한 코드의 TypeSelfType 이된다고했다.

extension String {
   func makeEmpty() -> Self {
       return Self()
   }
}

makeEmpty() 메서드는 현재 String 타입 내부에 있다.
그러니까 현재 속한 코드는 String 내부에 속해 있기 때문에 String 대신 Self 를 사용할수있다.

프로토콜의 경우
프로토콜 내부의 Self 는 자기자신(프로토콜)이 아닌 자신을 채택한 타입을 의미하게된다.
아래의 예시는 Decodable 이라는 프로토콜을 확장해서 메서드를 정의해주었다.

extension Decodable {
   static func parse(_ name: String) -> Self? {
       guard let asset = NSDataAsset(name: name) else >{
           return nil
       }
       let jsonData = try? >JSONDecoder().decode(Self.self, from: asset.data)

       return jsonData
   }
}

예시 코드를 보면 반환값이 Self 인걸 알수있다.
위의 설명만 보면 이해하기 어려울것 요 메서드 가 사용되는 것을 보면 이해가 쉽다.

let expositionItems =[ExpositionItems].parse(JsonFile.items)

위의 예시 코드에서 ExpositionItemsDecodable 을 채택하는 모델이다. ExpositionItems 요녀석이 Decodableparse() 메서드를 사용하게될경우 반환 타입은 무엇일까?

조금전 설명에서 프로토콜에서의 Self 는 자신을 채택하는 타입의 타입이 된다고 했다.
그러면 예상할수 있듯이 expositionItems 타입은 [ExpositionItems]? 가 된다.

'iOS > Swift-Memo' 카테고리의 다른 글

Swift Lint 란?, Swift Lint 적용방법  (0) 2022.04.29
Static Dispatch, Dynamic Dispatch  (0) 2022.04.29
JSON, Encoding, Decoding, Codable  (0) 2022.04.29
Assets 에서 Json 파일 읽기(NSDataAsset)  (0) 2022.04.29
CaseIterable  (0) 2022.02.19
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/07   »
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
글 보관함