在试图理解一个程序时,或者在某些极端情况下,找出某个东西的类型是很有用的。我知道调试器可以向您显示一些类型信息,在这些情况下,您通常可以依靠类型推断来避免不指定类型,但我仍然希望有类似Python的type()的东西。
dynamicType(参见这个问题)
更新:在Swift的最新版本中,obj已被更改。dynamicType现在提供了对类型的引用,而不是动态类型的实例。
这款似乎最有希望,但到目前为止我还没能找到实际的型号。
class MyClass {
var count = 0
}
let mc = MyClass()
# update: this now evaluates as true
mc.dynamicType === MyClass.self
我还尝试使用类引用来实例化一个新对象,这确实有效,但奇怪的是,给了我一个错误,说我必须添加一个必需的初始化器:
工作原理:
class MyClass {
var count = 0
required init() {
}
}
let myClass2 = MyClass.self
let mc2 = MyClass2()
不过,要真正发现任何给定对象的类型,这仍然只是一小步
编辑:我已经删除了大量现在不相关的细节-如果你感兴趣,看看编辑历史:)
斯威夫特2.0:
进行这种类型内省的正确方法是使用Mirror结构体,
let stringObject:String = "testing"
let stringArrayObject:[String] = ["one", "two"]
let viewObject = UIView()
let anyObject:Any = "testing"
let stringMirror = Mirror(reflecting: stringObject)
let stringArrayMirror = Mirror(reflecting: stringArrayObject)
let viewMirror = Mirror(reflecting: viewObject)
let anyMirror = Mirror(reflecting: anyObject)
然后要从镜像结构体中访问类型本身,你可以像这样使用属性subjectType:
// Prints "String"
print(stringMirror.subjectType)
// Prints "Array<String>"
print(stringArrayMirror.subjectType)
// Prints "UIView"
print(viewMirror.subjectType)
// Prints "String"
print(anyMirror.subjectType)
然后你可以这样使用:
if anyMirror.subjectType == String.self {
print("anyObject is a string!")
} else {
print("anyObject is not a string!")
}
dynamicType。printClassName代码来自Swift书籍中的一个示例。我不知道如何直接获取自定义类名,但可以使用is关键字检查实例类型,如下所示。这个例子还展示了如何实现一个自定义的className函数,如果你真的想要类名作为字符串。
class Shape {
class func className() -> String {
return "Shape"
}
}
class Square: Shape {
override class func className() -> String {
return "Square"
}
}
class Circle: Shape {
override class func className() -> String {
return "Circle"
}
}
func getShape() -> Shape {
return Square() // hardcoded for example
}
let newShape: Shape = getShape()
newShape is Square // true
newShape is Circle // false
newShape.dynamicType.className() // "Square"
newShape.dynamicType.className() == Square.className() // true
注意:NSObject的子类已经实现了他们自己的className函数。如果您正在使用Cocoa,您可以使用这个属性。
class MyObj: NSObject {
init() {
super.init()
println("My class is \(self.className)")
}
}
MyObj()
从Xcode 6.0.1开始(至少,不确定他们什么时候添加的),你原来的例子现在可以工作了:
class MyClass {
var count = 0
}
let mc = MyClass()
mc.dynamicType === MyClass.self // returns `true`
更新:
要回答最初的问题,您实际上可以成功地将Objective-C运行时与普通Swift对象一起使用。
试试下面的方法:
import Foundation
class MyClass { }
class SubClass: MyClass { }
let mc = MyClass()
let m2 = SubClass()
// Both of these return .Some("__lldb_expr_35.SubClass"), which is the fully mangled class name from the playground
String.fromCString(class_getName(m2.dynamicType))
String.fromCString(object_getClassName(m2))
// Returns .Some("__lldb_expr_42.MyClass")
String.fromCString(object_getClassName(mc))
如果您只是需要检查变量是否属于X类型,或者它是否符合某种协议,那么您可以使用is或as?具体如下:
var unknownTypeVariable = …
if unknownTypeVariable is <ClassName> {
//the variable is of type <ClassName>
} else {
//variable is not of type <ClassName>
}
这相当于Obj-C中的isKindOfClass。
这等价于conformsToProtocol或isMemberOfClass
var unknownTypeVariable = …
if let myClass = unknownTypeVariable as? <ClassName or ProtocolName> {
//unknownTypeVarible is of type <ClassName or ProtocolName>
} else {
//unknownTypeVariable is not of type <ClassName or ProtocolName>
}
斯威夫特2.0:
进行这种类型内省的正确方法是使用Mirror结构体,
let stringObject:String = "testing"
let stringArrayObject:[String] = ["one", "two"]
let viewObject = UIView()
let anyObject:Any = "testing"
let stringMirror = Mirror(reflecting: stringObject)
let stringArrayMirror = Mirror(reflecting: stringArrayObject)
let viewMirror = Mirror(reflecting: viewObject)
let anyMirror = Mirror(reflecting: anyObject)
然后要从镜像结构体中访问类型本身,你可以像这样使用属性subjectType:
// Prints "String"
print(stringMirror.subjectType)
// Prints "Array<String>"
print(stringArrayMirror.subjectType)
// Prints "UIView"
print(viewMirror.subjectType)
// Prints "String"
print(anyMirror.subjectType)
然后你可以这样使用:
if anyMirror.subjectType == String.self {
print("anyObject is a string!")
} else {
print("anyObject is not a string!")
}