David Neiss
David Neiss

Reputation: 8237

Swift upcasting with "as", whats going on?

protocol P1 {
    func doP1()
}
protocol P2 {
    func doP2()
}

class B {
}
class D : B, P1, P2 {
    func doP2() {}
    func doP1() {}
}

let s = D()
print(type(of:(D() as P1)))
print(type(of:(D() as B)))
print(type(of:[D(), D()] as [P1]))

So when I run this, i get:

D
D
Array<P1>

ok, so Im coming from the C++ world. I figured the first line would give me a type of P1, the second would give me a type of B, and the third would give me an array of P1. So I get the array of P1, but that seems inconsistant with the first line, which figures out that its really a D and not a P1. So what gives? Clearly,I don't understand this corner of Swift. When you upcast, shouldn't it disregard this type info? Is the compiler too smart, because it really knows the types?

Upvotes: 2

Views: 576

Answers (2)

matt
matt

Reputation: 536009

Is the compiler too smart, because it really knows the types?

The compiler knows only what you tell it. It thinks D() as B is a B.

But you didn't ask the compiler. When you say print and run the app, you're talking to the runtime. Polymorphism says that an object is the type it actually is, internally, and not some other type. You can cast D() to P1 or B but it is still a D. You run the app, the runtime discovers this, and it tells you what it discovered.

The Array situation is slightly different. In Swift, Array is a generic, and must be resolved. Your statement of how it should be resolved is decisive, even for the runtime:

print(type(of:[D(), D()] as [P1]))
print(type(of:[D(), D()] as [P2]))
print(type(of:[D(), D()] as [B]))
/*
 Array<P1>
 Array<P2>
 Array<B>
*/

In other words, the runtime doesn't bother to explore these arrays and tell you their lowest common denominator, as it were; it just tells you the type. But if you were to explore the arrays yourself, you'd find out what is in them:

for element in ([D(), D()] as [P1]) { print(type(of:element)) }
// D D

Upvotes: 2

Ewan Mellor
Ewan Mellor

Reputation: 6857

type(of: ...) in Swift returns the dynamic type of the value, not its static type. It's the equivalent of using RTTI in C++.

https://developer.apple.com/documentation/swift/2885064-type

Upvotes: 0

Related Questions