2014-12-15 2 views
7

Swift 상속 Objective-C의 메타 클래스 개념 : 클래스 자체도 객체로 간주됩니다. Foo 클래스의 객체 클래스는 Foo.self이고 유형은 Foo.Type입니다. FooBar에서 상속되는 경우 Foo.selfBar.Type 유형의 변수에도 할당 될 수 있습니다. 최소한 두 가지 이점이 있습니다.스위프트에서 프로토콜 유형에 메타 클래스 객체를 변환 할 수 있습니까?

  • "정적 방법"을 무시할 수 있습니다.
  • 리플렉션을 사용하지 않고 유형을 알 수없는 방식으로 알 수없는 클래스의 인스턴스를 만드는 것은 쉽습니다.

저는 특히 두 번째 것을보고 있습니다. 그냥 모두가 난 후 무엇을 이해하고 있는지 확인하기 위해, 여기에 예입니다 : 이제

class BaseFoo { 
    var description: String { return "BaseFoo" } 
} 

class DerivedFoo: BaseFoo { 
    override var description: String { return "DerivedFoo" } 
} 

let fooTypes: [BaseFoo.Type] = [BaseFoo.self, DerivedFoo.self] // metaclass magic! 
for type in fooTypes { 
    let object: BaseFoo = type() // metaclass magic! 
    println(object) 
} 

, 나는 AnyClass 객체 (어떤 메타 클래스 인스턴스가 어떤 객체를 할당 할 수있는 것처럼, AnyClass에 할당 할 수의 배열을 가지고 ~ AnyObject), 나는 주어진 프로토콜을 구현하는 프로토콜을 찾고 싶습니다. 프로토콜은 이니셜 라이저를 선언 할 것이고 위의 예에서와 같이 클래스를 인스턴스화합니다. 예 :

protocol Foo { 
    init(foo: String) 
} 

class Bar: Foo { 
    required init(foo: String) { println("Bar initialized with \(foo)") } 
} 

class Baz { 
    required init() { println("I'm not a Foo!") } 
} 

let types: [AnyClass] = [Bar.self, Baz.self] 

지금까지는 그렇게 좋았습니다. 이제 문제는 클래스가 프로토콜을 구현하는지 결정하는 것입니다. 메타 클래스 인스턴스는 다형성을 가지므로이를 캐스팅 할 수 있기를 기대합니다. 스위프트 날이 쓸 수 없기 때문에 그러나, 나는 분명히 뭔가를 누락 :

for type in types { 
    if let fooType = type as? Foo.Type { 
     let obj = fooType(foo: "special snowflake string") 
    } 
} 

내가받을 컴파일러 오류는 다음과 같습니다

오류 : '푸'는 동일하지 'AnyObject'

메타 클래스 인스턴스가 프로토콜을 구현하는 클래스를 나타내는 지 확인할 수있는 방법이 있습니까?이 인스턴스를 프로토콜 유형으로 변환 할 수있는 방법이 있습니까?

Foo을 클래스 프로토콜로 선언하려고했지만 분명히 충분하지 않습니다.


편집 : 난 그냥 Any 유형을 시도하고 구문 오류가 발생하지 않지만, 그것은 스위프트 컴파일러가 충돌합니다.

+0

컴파일러 추락 사용할 수 있습니다 : 당신은 지금 쓸 수있다? [버그 신고] (http://bugreport.apple.com). – rickster

+0

나는 이미 그렇게했다. – zneak

+0

예! 실제 문제에 관해서는, 현재의 스위프트에서 메타 클래스가 내성적인지 확신 할 수 없습니다. – rickster

답변

4

Xcode 7 beta 2 및 Swift 2부터 수정되었습니다.

for type in types { 
    if let fooType = type as? Foo.Type { 
     // in Swift 2 you have to explicitly call the initializer of metatypes 
     let obj = fooType.init(foo: "special snowflake string") 
    } 
} 

을 또는 당신은 단지 형식으로 type을 원하는 경우 Foo.Type 당신은 for case

for case let type as Foo.Type in types { 
    let obj = type.init(foo: "special snowflake string") 
} 
관련 문제