Type Casting

Type casting in Swift is implemented with is and as operators.

Type casting:

  • A subclass instance can be use as a superclass instance.

Defining a Class Hierarchy

class Media {    var name: String    init(name: String) {        self.name = name    }}class Song: Media {    var artist: String    init(name: String, artist: String) {        self.artist = artist        super.init(name: name)    }}class Movie: Media {    var director: String    init(name: String, director: String) {        self.director = director        super.init(name: name)    }}var library = [    Movie(name: "A", director: "Michael"),    Song(name: "B", artist: "Elvis"),    Movie(name: "C", director: "Orson"),    Song(name: "D", artist: "Rick"),    Media(name: "E")]// The "library" is inferred to be [Media] for item in library {    print(item.name)  // Here the item is of "Media" type }// If we want to use the library's item as the subclass instance, we should downcast the item.

Checking Type

Use is to check whether an instance is of a certain subclass type.

for item in library {    if item is Movie {        print(item.name + " is Movie")    } else if item is Song {        print(item.name + " is Song")    } else {                print(item.name + " is Media")        }}

When set the movies and songs to the library, it's the automatically upcast. The upcast is a type of polymorphism.

Downcasting

When we believe that a superclass instance is actually of a subclass type, we can downcast the instance to be a subclass type.

Two way to downcast a instance:

  • as? get an optional result. (Recommended)
  • as! force downcast, it will trigger runtime error when the types not match.
for item in library {    if let movie = item as? Movie {        print(movie.name + " " + movie.director)    } else if let song = item as? Song {        print(song.name + " " + song.artist)    }}// Print:// A Michael// B Elvis// C Orson// D Rick// E is just a Media

Type Casting for Any and AnyObject

  • Any can represent an instance of any type at all, including function type, including class type.
  • AnyObjece can represent an instance of any class type.
var things: [Any] = []things.append(0)var a: Int? = 3things.append(a as Any)things.append(4.0)things.append(42)things.append("Oh")things.append((2.0, 3.5))things.append(Media(name: "LoL"))things.append({(name: String) -> String in "Hello, \(name)"})for thing in things {    switch thing {    case is Int:        print("\(thing) is Int")    case let someDouble as Double where someDouble > 2:        print("Double \(someDouble) is greater than 2")    case is Double:         print("\(thing) is Double")    case let s as String:         print("\(thing) is String")    case let (x, y) as (Double, Double):        print("x: \(x) y: \(y)")    case let media as Media:         print("Media: \(media.name)")    case let say as (String) -> String:        print("Func: \(say("John"))")    default: break            }}// Print:// 0 is Int// Optional(3) is Int// Double 4.0 is greater than 2// 42 is Int// Oh is String// x: 2.0 y: 3.5// Media: LoL// Func: Hello, John

If we want to use an optional variable as Any , write as Any , otherwise

Swift will give us a warning.

var a: Int? = 3things.append(a)        // Warningthings.append(a as Any) // No warning