Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Archives
Today
Total
관리 메뉴

sanichdaniel의 iOS 개발 블로그

Metatype 본문

swift

Metatype

sanich8355 2020. 9. 3. 23:37

Metatype 타입이란, 타입의 타입입니다. 

class, structure, or enum의 메타타입은 자신의 이름 뒤에 .Type이 옵니다.
protocol 타입의 메타타입은 이름 뒤에  .Protocol 이 옵니다.

 

class Some { }

let someType: Some = Some()
let metaSomeType: Some.Type = type(of: Some())

 

Some 타입은 Some 클래스의 인스턴스 타입이고

Some.Type은 Some 클래스 자체의 타입 = 메타타입

 

.self

postfix .self 를 이용하여 타입을 값으로 접근할수 있습니다.

 

SomeClass.self  SomeClass 의 인스턴스가 아닌, SomeClass 타입 자체를 리턴합니다.

SomeProtocol.self 도 런타임에 프로토콜을 채택한 타입의 인스턴스가 아니라, SomeProtocol 자체를 리턴합니다.

 

// "Hello World" 가 값
// String이 타입
let myString: String = "Hello World"

// String.self가 메타타입의 값
// String.Type 이 타입
let metaString: String.Type = String.self

 

.self 는 static metatype 을 반환합니다. 컴파일 타임의 타입
※ type(of:) 는 dynamic metatype을 반환합니다 

 

 

타입의 메타타입에 init() 함수를 호출하여 인스턴스를 만들거나,  클래스 프로퍼티, 메소드접근할수 있습니다.

이때 class는 final 이거나, required 생성자가 있어야 합니다. 이유

 

class AnotherSubClass: SomeBaseClass {
    let string: String
    required init(string: String) {
        self.string = string
    }
    override class func printClassName() {
        print("AnotherSubClass")
    }
}
let metatype: AnotherSubClass.Type = AnotherSubClass.self
let anotherInstance = metatype.init(string: "some string")

 

Protocol Metatype

아래 코드는 컴파일이 안됩니다.

protocol MyProtocol {}
let metatype: MyProtocol.Type = MyProtocol.self // 에러!!!

MyProtocol.Type 은 프로토콜을 채택한 타입의 메타타입(existential metatype)을 가리키기 때문입니다.

 

protocol MyProtocol {}
struct MyType: MyProtocol {}
let metatype: MyProtocol.Type = MyType.self // Now works!

위의 경우 metatype은 MyProtocol의 프로퍼티나 메서드만 접근이 가능하지만 정작 불리는건 MyType의 구현입니다.

프로토콜의 concrete metatype 을 접근하려면 위에서 설명했던 .Protocol 을 사용하면 됩니다.

 

let protMetatype: MyProtocol.Protocol = MyProtocol.self

채택이 안된 프로토콜 프로토콜 메타타입 protMetatype은 간단한 타입 체크 protMetatype is MyProtocol.Protocol 에서만 사용이 되고 실제로는 사용될일이 거의 없다.

컴파일단에서 사용된다고 한다.

 

실험 (출처: devmjun.github.io/archive/Meta_Type_Swift)

print("\n---------- [ Instance Type Check ] ----------\n")

let str = "StringInstance"
print(str is String)           // true, str 은 String Type 의 객체, 스트링의 객체가 맞으면 참트루
print(str == "StringInstance") // true, str 은 "StringInstance" 와 동일
print(str is String.Type)      // false
print(str is String.Type.Type) // false



print("\n---------- [ Type's Type check ] ----------\n")

print(type(of: str) is String)       // false, String is String 과 동일.. 그니까 String == String.Type을 물어본거
print(type(of: str) == String.self)  // true, str 객체의 타입은 String 그 자체, String.Type == String.Type
print(type(of: str) is String.Type)  // true, str 객체의 타입은 String.Type 의 객체 String의 타입 == String.type



print("\n---------- [ Metatype's Type check ] ----------\n")

private let meta = type(of: String.self)
print(meta is String)  // false
print(meta == String.self)  // false
print(meta == String.Type.self)  // true, String 메타타입은 String.Type
print(meta is String.Type.Type)  // true, String 메타타입은 String.Type.Type 의 객체

사용되는곳

디코딩, 테이블뷰 셀 등록, 또는 객체를 생성해주는 함수에서 인자로 MetaType을 받는 케이스가 있다(ex. 팩토리)

func decode<T>(_ type: T.Type, from: Self.Input) throws -> T where T : Decodable

// typealias AnyClass = AnyObject.Type
func register(_ cellClass: AnyClass?, forCellReuseIdentifier identifier: String)


출처: swiftrocks.com/whats-type-and-self-swift-metatypes

'swift' 카테고리의 다른 글

enum vs protocol as UseCase  (0) 2020.09.28
Type Erasure  (0) 2020.09.28
initializer  (0) 2020.09.26
Self Type  (0) 2020.09.05
type(of:)  (0) 2020.09.05