其实Apple在Swift 2.x的时候就引入了typeof函数,用于获取某一对象的元类型。在Swift 3.0中,该函数被重新命名为type(of:)。由于反射机制大幅度修改,Mirror现在也用不了了,所以type(of:)这个函数是为数不多的关于Swift中的反射接口。
type(of:)函数相当于什么呢?如果我们用过Objective-C的话,它就相当于NSObject中的class实例方法,返回当前对象所对应类的元类型(Metatype of the class)。我们通过此元类型可以作为该类类方法的消息接收者。在Swift中也一样,Swift 3.0中,我们可以用类的元类型来访问该类的类属性与类方法。这里插句题外话,Apple在Swift 3.0中已经引入了Self关键字,但是我们现在还不能用它,它的作用就相当于Objective-C中的class实例方法,用于直接获取当前类的元类型,然后可以用它直接访问类的类属性与类方法,但是具体怎么实现,Swift核心团队正在讨论,这里涉及到许多问题,包括在类体内是否能直接使用等等,所以有可能的话Self将作为每个结构体、枚举、类的属性来使用——比如,self.Self.classMethod(),而不是直接使用Self.classMethod()。
当然,就目前而言,如果我们想在一个实例方法中方便访问当前类的类属性和类方法,那么可以直接使用type(of: self)即可,这可能比直接用ClassName.classMethod()要更通用化一些,或更简洁一些(如果你的类名比较长的话)。
下面给出一段代码例子:
class MyClass { fileprivate static let aa = 100 required init() { print("Hello,world") } func method() { // 这里的a是MyClass的元类型(Metatype of MyClass) let a = type(of: self) // 这里直接通过MyClass的元类型对象a来访问MyClass的类成员aa var value = a.aa print("The value is: \(value)"); // 这里的b是Int的类型(Metatype of Int) let b = type(of: a.aa) // 如果要通过一个元类型来创建一个对象实例,那么必须显式地调用该结构体或类的构造方法 value = b.init(20) print("The integer is: \(value)") // 一个结构体或类的元类型可以直接用该结构体或类名访问Type属性即可表示。 // 但这里要注意的是,像这里的Int.Type只能作为对象的类型进行声明,而不能作为一个表达式来使用。 // 所以,它也不能作为type(of:)函数的实参进行传递 let c: Int.Type = type(of: type(of: self).aa) value = c.init("1234")! print("The value is: \(value)") } } // 这一句会输出Hello,world var type = type(of: MyClass()) // 这里通过type类型显式调用init构造方法也会直接输出一次Hello,world var mc = type.init() // 这里直接将MyClass类的元类型给type type = MyClass.self mc = type.init() mc.method()
上述代码,各位可以直接用Xcode创建一个macOS的Cocoa Application来运行。当然也可以把上述的MyClass单独截出来运行。