我对Swift中的动态类型检查感到困惑。
具体来说,我有一个怪异的情况,我想在本质上写一个(或找到)一个函数:
func isInstanceOf(obj: Any, type: Any.Type) -> Bool
在Objective-C中,这是isKindOfClass
,但这不起作用,因为Any.Type
包含Swift结构,它不是类(更少NSObject
个子类)。
我不能在这里使用Swift is
,因为这需要硬编码类型。
我无法使用obj.dynamicType == type
,因为这会忽略子类。
Swift book似乎表明此信息已丢失,根本不适用于结构:
类具有结构不具备的附加功能:
...
- 类型转换使您可以在运行时检查和解释类实例的类型。
(在类型转换章节中,它说“Swift中的类型转换是使用is和as运算符实现的”,因此它似乎是比“{3}}更广泛的”类型转换定义。)
但是,is
/ as
不能与结构一起使用,因为您可以将字符串和Ints放入[Any]
,然后将它们拉出来,并使用is String
或is Int
来确定它们是什么。 Swift Book的Type Casting章就是这样做的!
是否存在与isKindOfClass
一样强大但对于任何Swift实例的东西?这些信息仍然必须在运行时存在,对吗?
答案 0 :(得分:6)
实际上您可以使用is
运算符。
使用类型检查运算符(is)检查实例是否属于某个子类类型。如果实例属于该子类类型,则类型检查运算符返回true,否则返回false。
由于struct
不能被子类化,因此is
在应用于struct的实例时保证是一致的,因为它将检查它的静态类型,对于类,它将查询动态在运行时输入。
func `is`<T>(instance: Any, of kind: T.Type) -> Bool{
return instance is T;
}
这项工作适用于struct
和class
。
答案 1 :(得分:1)
如前所述,是/应该可以正常使用结构。其他极端情况通常可以使用泛型函数来完成,例如:
let thing: Any = "hi" as Any
func item<T: Any>(_ item: Any, isType: T.Type) -> Bool {
return (item as? T) != nil
}
print(item(thing, isType: String.self)) // prints "true"
不知道这是否适合您的特定用例。
更一般地说,请记住,Swift(当前)需要在编译时知道所有内容的类型。如果无法定义将传递给函数或设置为变量的特定类型,则编译器也不会。