์ด์ ์ metatype์ ๋ํด ํ๋ ค๋ค์์๋๋ฐ, ์ด๋ฒ์ ๊ฐ๋จํ๊ฒ ์ ๋ฆฌํด๋ณด๋ คํ๋ค.
metatype์ด๋?
Swift์์ ์ฐ๋ฆฌ๋ ํน์ instance์ Type์ ์ ๊ทผํ ์ ์๋ค.
struct SomeStruct {
static let variable: String = "HI"
}
let someStruct = SomeStruct()
let someStructType = type(of: someStruct)
let someStructStaticVariable = someStructType.variable
print(someStructStaticVariable) // HI๊ทธ๋ผ ์ฌ๊ธฐ์ someStructType์ ์ด๋ค Type์ผ๊น? ์ด๋
์์ SomeStruct.Type์ด๋ผ ๋์ด์๋ค. ๋ฐ๋ก ์ด๋
์์ด metatype์ด๋ค.
์ด๋ ๊ฒ ๋ฐ์ metaType์, ViewController.init()์ ํ์ฌ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ๊ฒ์ฒ๋ผ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. ์ด๋ฌํ ์ ์ ์ด์ฉํ๋ฉด ์ธ์๋ก metatype์ ๋ฐ์ ํด๋น metatype์ instance๋ฅผ ๋ง๋๋ ๊ฒ๋ ๊ฐ๋ฅํ๋ค.
class Apple {
required init() {}
}
func createApple<T: Apple>(appleType: T.Type) -> T {
return appleType.init()
}
let apple = self.createApple(appleType: Apple.self)
print(apple) // test.apple์ฌ๊ธฐ์ ๊ทธ๋ฐ๋ฐ ์ธ์๋ก ๋ฃ์ด์ค ๋ Apple.self ๋ก ๋ฃ์ด์ฃผ์๋ค. ์ด๋
์์ ๋ญ๊น?
metatype์ Value
let a: Int = 3์ฌ๊ธฐ์ a์ Type์ Int์ด๊ณ , Value๋ 3์ด๋ค. ๊ทธ๋ผ class, struct, enum ์์ฒด์ ์ ๊ทผํ ๋ ์์ type๊ณผ value๋ ์์ง ์์๊น?
| Type | Value | ์์ | |
|---|---|---|---|
| Instance | Int, String | 3, โwansikโ | let a: Int = 3 |
| Class, Struct ์์ฒด | Int.Type, String.Type | Int.self, String.self | let a: Int.Type = Int.self |
์ด๋ฐ ์ด์ ๋๋ฌธ์, createApple<T: Apple>(appleType: T.Type) -> T์์ T.Type์ class, struct, enum ์์ฒด์ metatype์ type์ ๋งํ๊ณ , ์ค์ ๊ฐ์ Apple.self๋ก class, struct, enum ์์ฒด์ value๋ฅผ ๋ฃ์ด์ค ๊ฒ์ด๋ค.
Protocol metatype
๊ทธ๋ฐ๋ฐ protocol์์๋ ์ด ๋ ผ๋ฆฌ๊ฐ ํตํ์ง ์๋๋ค.
protocol MyProtocol {}
let metatype: MyProtocol.Type = MyProtocol.self // compile Error์ด๋ MyProtocol.Type์ด protocol ์์ฒด์ metatype์ type์ ๊ฐ๋ฆฌํค์ง ์๊ธฐ ๋๋ฌธ์ด๋ค. ์ฅ? ๊ทธ๋ผ ๋ญ ๊ฐ๋ฆฌํฌ๊น? ์ด ํ๋กํ ์ฝ์ ์ค์ํ๊ณ ์๋ Type์ metatype์ ๊ฐ๋ฆฌํจ๋ค. ์ฆ, Protocol์ ์ถ์ ์ธํฐํ์ด์ค์ด๊ธฐ ๋๋ฌธ์, ์ค์ ์ด๋ฅผ ์ค์ํ๋ ๋
์์ด ๊ตฌํ์ฒด์ธ๋ฐ, ์ด๋
์์ metatype์ ๊ฐ๋ฆฌํจ๋ค๋ ๊ฒ์ด๋ค. Apple์ ์ด๋ฅผ existential metatype, ์ค์กด ๋ฉํํ์
์ด๋ผ๊ณ ๋ถ๋ฅธ๋ค. ์ฝ๋๋ฅผ ๋ณด์.
protocol MyProtocol {
static func test()
}
struct MyType1: MyProtocol {
static func test() {
print("my type1")
}
}
struct MyType2: MyProtocol {
static func test() {
print("my type2")
}
}
let metatype1: MyProtocol.Type = MyType1.self
let metatype2: MyProtocol.Type = MyType2.self
metatype1.test() // my type1
metatype2.test() // my type2์ฆ, ์ด ๊ฒฝ์ฐ metatype1, 2 ๋ณ์๋ MyProtocol์ static property ๋๋ method์๋ง ์ ๊ทผ ๊ฐ๋ฅํด์ง๋ค. ์๋ฐํ ๋งํ๋ฉด MyType struct์ ๊ตฌํ์ฒด๊ฐ ๋ถ๋ฆฐ๋ค. ๊ทธ๋์ ์ค์ ๊ตฌํ์ฒด์ ๊ฐ์ด ํธ์ถ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๊ทธ๋ผ protocol ์์ฒด์ type์ ์ด๋ป๊ฒ ์ ๊ทผํ ์ ์์๊น?
let protocolType: MyProtocol.Protocol = MyProtocol.self์ด๋ ๊ฒ ํ๋ฉด ์ป์ ์๋ ์์ง๋ง, ์ค์ ๊ธฐ๋ณธ ๊ตฌํ์ ์ ๊ทผํด์ ์ฌ์ฉํ ์ ์๊ธฐ ๋๋ฌธ์ ์ค์ง์ ์ผ๋ก ์ฌ์ฉํ๊ธฐ๋ ์ด๋ ค์๋ณด์ธ๋ค.