Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Given that the underlying types are the same, I expected test2 to be true, not 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
    }
}

Is this due to the difference between a concrete metatype of a class vs the existential metatype of a protocol instance?

like image 522
Noel Avatar asked Nov 25 '25 09:11

Noel


1 Answers

After taking a look at the documentation of type(of:) function we can rephrase the last paragraph to something like this:

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:).

or just change the compare(expected:actual:) function to use Any type instead of generics:

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

Update: Even better you can use @Jessy suggestion in the comments

func compare<Expected: Foundation.NSObject>(expected: Expected.Type, actual: Any) -> Bool {
    return type(of: actual) is Expected.Type
}
like image 107
gcharita Avatar answered Nov 27 '25 23:11

gcharita



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!