Shubhashis
Shubhashis

Reputation: 10631

Confusion about type casting in swift

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

Answers (1)

vacawama
vacawama

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

Related Questions