我正在思考这个问题的答案:如何测试泛型变量是否属于 AnyObject 类型
该解决方案似乎不再起作用。我有以下代码:
public struct ObjectHashable<T>: Hashable {
public let object: T
public init(object: T) {
let t1 = type(of: object)
let b1 = t1 is AnyClass
print(t1) // Plugin
print(b1) // false
let t2 = T.self
let b2 = t2 is AnyClass
print(t2) // Plugin
print(b2) // false
let t3 = Mirror(reflecting: object).subjectType
let b3 = t3 is AnyClass
print(t3) // P
print(b3) // true
self.object = object
}
public static func ==(lhs: Self, rhs: Self) -> Bool {
return true
}
public func hash(into hasher: inout Hasher) {
}
}
protocol Plugin: AnyObject {}
class P: Plugin {}
typealias PluginHashable = ObjectHashable<Plugin>
PluginHashable(object: P())
这是一个令人惊讶的行为。
1.
let t1 = type(of: object)
type(of:)
应该返回动态类型,即P
,而不是Plugin
。但我打印出了“插件”。
2.
let b1 = t1 is AnyClass
因为 t1 是引用类型,所以它不应该是真的吗?(基于此处的答案:如何测试泛型变量是否属于 AnyObject 类型)
3.
let t2 = T.self
打印出来Plugin
,这是有道理的,因为我输入Plugin
了<>
4.
let b2 = t2 is AnyClass
这是错误的,但我认为出于同样的原因,它应该是正确的
5.
let t3 = Mirror(reflecting: object).subjectType // P
打印出来P
,这是有道理的
6.
let b3 = t3 is AnyClass // true
确实如此,这很有道理。但为什么它与其他两种情况不同呢?
这种意外行为记录在名为“在通用上下文中查找动态类型”的部分中:
在您的示例中,
P
应该是Plugin
协议。为了扩展文档中的解释,该type(of:)
函数有一些不寻常的类型检查规则。也就是说,如果编译器发现其参数是存在类型,它将允许整个表达式的类型
type(of:)
成为具体元类型,否则该类型与存在类型的元类型完全无关。然而
ObjectHashable
, 的类型object
是T
。编译器不知道这any Plugin
稍后会绑定到存在类型,因此它不会对存在类型应用这种特殊的类型检查规则。type(of: object)
基本上等同于T.self
。在此提交中,的行为
type(of:)
已更改为如下方式,这是在链接答案发布后发生的。正如文档所示,在将其放入之前转换
object
为存在类型(最简单的是)将按预期工作。Any
type(of:)
关于第 2 和第 4 点,其实没什么好解释的。它们根本不是类。仅仅因为
Plugin
是类约束的,并不意味着存在类型any Plugin
就是类。存在类型与具体类型截然不同。SE -0335建议所有存在类型都应以 为前缀,any
以突出这一区别。