Swift inherited Objective-C's metaclass concept: classes themselves are also considered objects. A class Foo
's object's class is Foo.self
, and it is of type Foo.Type
. If Foo
inherits from Bar
, then Foo.self
can be assigned to a variable of type Bar.Type
, too. This has at least two benefits:
Swift继承了Objective-C的元类概念:类本身也被认为是对象。类Foo的对象的类是Foo.self,它的类型为Foo.Type。如果Foo继承自Bar,那么Foo.self也可以分配给Bar.Type类型的变量。这至少有两个好处:
- it allows to override "static methods";
- 它允许覆盖“静态方法”;
- it's easy to create an instance of an unknown class in a type-safe way and without using reflection.
- 以类型安全的方式创建未知类的实例并且不使用反射很容易。
I'm particularly looking at the second one right now. Just to be sure that everybody understands what I'm after, here's an example:
我现在特别关注第二个。只是为了确保每个人都理解我所追求的,这是一个例子:
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)
}
Now, I have an array of AnyClass
objects (any metaclass instance can be assigned to AnyClass
, just like any object can be assigned to AnyObject
), and I want to find which ones implement a given protocol. The protocol would declare an initializer, and I would instantiate the class just like I do in the example above. For instance:
现在,我有一个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]
So far so good. Now, the problem is determining if the class implements the protocol. Since metaclass instances are polymorphic, I'd expect to be able to cast them. However, I'm apparently missing something, because Swift won't let me write this:
到现在为止还挺好。现在,问题在于确定类是否实现了协议。由于元类实例是多态的,我希望能够转换它们。但是,我显然错过了一些东西,因为Swift不会让我这样写:
for type in types {
if let fooType = type as? Foo.Type {
let obj = fooType(foo: "special snowflake string")
}
}
The compiler error I get is:
我得到的编译器错误是:
error: 'Foo' is not identical to 'AnyObject'
错误:'Foo'与'AnyObject'不同
Is there any way to determine if a metaclass instance represents a class that implements a protocol, and is there any way to cast that instance into a protocol type?
有没有办法确定元类实例是否表示实现协议的类,有没有办法将该实例强制转换为协议类型?
I tried to declare Foo
as a class protocol, but it's apparently not enough.
我试图将Foo声明为类协议,但显然还不够。
EDIT: I just tried with the Any
type, and while it doesn't cause a syntax error, it crashes the Swift compiler.
编辑:我刚尝试使用Any类型,虽然它不会导致语法错误,但它会崩溃Swift编译器。
1 个解决方案
#1
4
As of Xcode 7 beta 2 and Swift 2 it has been fixed. You can now write:
从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")
}
}
Or if you only want type
as type Foo.Type
you can use for case
或者,如果您只想将类型作为Foo.Type类型,则可以使用case
for case let type as Foo.Type in types {
let obj = type.init(foo: "special snowflake string")
}
#1
4
As of Xcode 7 beta 2 and Swift 2 it has been fixed. You can now write:
从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")
}
}
Or if you only want type
as type Foo.Type
you can use for case
或者,如果您只想将类型作为Foo.Type类型,则可以使用case
for case let type as Foo.Type in types {
let obj = type.init(foo: "special snowflake string")
}