2014-12-15 21 views
7

Swift thừa hưởng khái niệm metaclass của Objective-C: các lớp cũng được coi là các đối tượng. Lớp học của lớp học FooFoo.self, và nó thuộc loại Foo.Type. Nếu Foo kế thừa từ Bar, thì Foo.self cũng có thể được gán cho biến loại Bar.Type. Điều này có ít nhất hai lợi ích:Tôi có thể bỏ một đối tượng metaclass vào một loại giao thức trong Swift không?

  • nó cho phép ghi đè "phương pháp tĩnh";
  • thật dễ dàng để tạo một thể hiện của một lớp không xác định theo cách an toàn và không sử dụng sự phản chiếu.

Tôi đặc biệt đang xem mục thứ hai ngay bây giờ. Chỉ cần chắc chắn rằng tất cả mọi người hiểu được những gì tôi là sau đó, đây là một ví dụ:

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) 
} 

Bây giờ, tôi có một loạt các AnyClass đối tượng (bất kỳ trường hợp metaclass thể được gán cho AnyClass, giống như bất kỳ đối tượng có thể được gán đến AnyObject) và tôi muốn tìm cái nào thực hiện giao thức đã cho. Giao thức sẽ khai báo một initializer, và tôi sẽ khởi tạo lớp giống như tôi làm trong ví dụ trên. Ví dụ:

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] 

Cho đến nay rất tốt. Bây giờ, vấn đề đang xác định nếu lớp thực hiện giao thức. Vì các trường hợp metaclass có tính đa hình, tôi mong đợi có thể truyền chúng. Tuy nhiên, tôi dường như thiếu một cái gì đó, bởi vì Swift sẽ không cho phép tôi viết những dòng này:

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

Các lỗi biên dịch tôi nhận được là:

lỗi: 'Foo' là không giống với 'AnyObject'

Có cách nào để xác định xem một cá thể metaclass đại diện cho một lớp thực hiện giao thức và có cách nào để truyền thể hiện đó vào một loại giao thức không?

Tôi đã cố gắng khai báo Foo làm giao thức lớp học, nhưng dường như chưa đủ.


EDIT: Tôi chỉ thử với loại Any, và trong khi nó không gây ra một lỗi cú pháp, nó bị treo trình biên dịch Swift.

+0

Crashed trình biên dịch? [Lỗi tệp] (http://bugreport.apple.com). – rickster

+0

Tôi đã làm điều đó rồi. – zneak

+0

Yay! Đối với vấn đề thực tế, tôi không chắc metaclasses là introspectable trong Swift hiện tại. – rickster

Trả lời

4

Kể từ Xcode 7 beta 2 và Swift 2, nó đã được sửa. Bây giờ bạn có thể viết:

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") 
    } 
} 

Hoặc nếu bạn chỉ muốn type as type Foo.Type bạn có thể sử dụng for case

for case let type as Foo.Type in types { 
    let obj = type.init(foo: "special snowflake string") 
} 
Các vấn đề liên quan