转换为协议实例的变量与 class 实例的变量的底层类型不同?

Variable cast as protocol instance not the same underlying type as variable of class instance?

鉴于底层类型相同,我预计 test2true,而不是 false:

protocol Foo {}
class Bar: NSObject, Foo {}
class Test {
    func testCompare() {
        let b = Bar()
        let test1 = compare(expected: Bar.self, actual: b)
        let c: Foo = b
        let test2 = compare(expected: Bar.self, actual: c)
        /*
         (lldb) p expected
         (@thick NSObject.Type) $R0 = SpokestackTests.Bar
         (lldb) p type(of: actual).self
         (SpokestackTests.Foo.Type) $R2 = SpokestackTests.Bar
        */
        print(test1, test2) // true false
    }
    
    func compare<T>(expected: NSObject.Type, actual: T) -> Bool {
        return expected == type(of: actual).self
    }
}

这是由于 class 的具体元类型与协议实例的存在元类型之间的差异吗?

查看 type(of:) 函数的文档后,我们可以将最后一段改写成这样:

This unexpected result occurs because the call to type(of: value) inside compare(expected:actual:) must return a metatype that is an instance of T.Type which is the static type of actual parameter (Foo.self). To get the dynamic type inside value in this generic context, cast the parameter to Any when calling type(of:).

或者只是更改 compare(expected:actual:) 函数以使用 Any 类型而不是泛型:

private func compare(expected: NSObject.Type, actual: Any) -> Bool {
    return expected == type(of: actual).self
}

更新:更好的是你可以在评论中使用@Jessy的建议

func compare<Expected: Foundation.NSObject>(expected: Expected.Type, actual: Any) -> Bool {
    return type(of: actual) is Expected.Type
}

它可以像比较相同的对象一样与您的函数进行比较

它无法与实例进行元类型比较,所以 returns 错误 这些 returns false 你也可以在 pg 中试试 :

    let d: Any = b
    _ = compare(expected: Bar.self, actual: d)
    
    d as! Foo
    _ = compare(expected: Bar.self, actual: d)