Reputation: 10631
I was toying in the playground in xcode 7.3.1 with swift. I am a bit confused about the type casting in swift.
So, here is a bit of code that I tried.
class MediaItem {
var name: String
init(name: String) {
self.name = name
}
}
class Movie: MediaItem {
var director: String
init(name: String, director: String) {
self.director = director
super.init(name: name)
}
}
class Song: MediaItem {
var artist: String
init(name: String, artist: String) {
self.artist = artist
super.init(name: name)
}
}
var movieItem = Movie(name: "GOT", director: "RRMartin")
movieItem.dynamicType //Movie.Type
(movieItem as? MediaItem).dynamicType //Optional<MediaItem>.Type
var someItm = movieItem as! MediaItem //Movie
someItm.dynamicType //Movie.Type
I've shown the output from the playground in the comment. Here you can see the type in each line.
Now according the docs of apple, The conditional form, as?, returns an optional value of the type you are trying to downcast to.
As per the docs, I am trying to downcast to MediaItem, and I am getting the MediaItem as optional type.
But when I use force unwrap(that is as!
) the returned type is Movie
. But I wanted it to be MediaItem
.
Also, another thing to notice is that, the type is actually changed. Some data are actually truncated. Because when I tried to access the director
property which is present in the Movie, I cannot access it. As I've downcast it.
So, if the type is downcast, why the returned type is Movie
? Shouldn't it be MediaType
?
So, my question is this, when I type cast some derived class(Movie
) to base class(MediaType
), shouldn't the converted type be base class(MediaType
)?
Upvotes: 2
Views: 290
Reputation: 154721
dynamicType
tells you what the underlying type of the object is. It doesn't tell you what the type of var
currently referencing that object is.
For instance:
let a: Any = 3
a.dynamicType // Int.Type
Swift, of course, keeps track of these underlying types which is what allows you to later downcast a MediaItem
to a Movie
(if that is what it really is).
The confusion for you came when you did:
(movieItem as? MediaItem).dynamicType //Optional<MediaItem>.Type
An Optional is it's own type. It is an enumeration with two values: .None
and .Some(T)
. The .Some
value has an associated value that has its own dynamic type. In your example, when you asked for the dynamicType
, it returned the underlying type of the Optional which is Optional<MediaItem>.Type
. It didn't tell you what the dynamic type of the value associated with that Optional is.
Consider this:
let x = (movieItem as? MediaItem)
x.dynamicType // Optional<MediaItem>.Type
x!.dynamicType // Movie.Type
Upvotes: 3