Chapters

Hide chapters

Swift Cookbook

Live Edition · Multiplatform · Swift · Editor agnostic

Type Casting in Swift
Written by Team Kodeco

Type casting in Swift is the process of converting an object from one type to another.

The syntax of type casting in Swift is as follows:

expression as Type

Her’s an example of using Swift type casting:

let stringValue = "hello"
let intValue = 42

let doubleValue = Double(intValue) // 42.0
let stringDoubleValue = Double(stringValue) // This will fail and return nil

The first typecast converts an integer to a Double.

The second typecast tries to convert a string “hello” to a Double. Since “hello” is not a number, the typecast fails and returns nil.

Downcasting vs. Upcasting

There are two types of type casting in Swift: downcasting and upcasting.

Downcasting is used to convert a value from a superclass type to a subclass type. The syntax for downcasting is as follows:

let instance = superclassValue as? SubclassType

The as? operator is used to perform a downcast and returns an optional value of type SubclassType. If the downcast is successful, the optional will contain the downcasted value, otherwise it’ll be nil.

Upcasting is used to convert a value from a subclass type to a superclass type. The syntax for upcasting is as follows:

let instance: SuperclassType = subclassValue as SuperclassType

The as operator is used to perform an upcast. If the upcast is successful, the expression will be of type SuperclassType, otherwise it’ll cause a compile-time error.

In both cases, the type casting is performed at runtime, which means that the type of the value can only be determined at runtime, not at compile time. This is why type casting can be unsafe, so it’s important to use it with caution and check the type of the casted value before using it.

Downcasting in Swift

An example for downcasting:

class MediaItem {
  var name: String
  init(name: String) {
    self.name = name
  }
}

class Song: MediaItem {
  var artist: String
  init(name: String, artist: String) {
    self.artist = artist
    super.init(name: name)
  }
}

class Movie: MediaItem {
  var director: String
  init(name: String, director: String) {
    self.director = director
    super.init(name: name)
  }
}

let library = [
  Song(name: "Never Gonna Give You Up", artist: "Rick Astley"),
  Movie(name: "The Matrix", director: "Wachowski"),
  Song(name: "Smooth Criminal", artist: "Michael Jackson"),
  Movie(name: "Inception", director: "Christopher Nolan"),
  Song(name: "Billie Jean", artist: "Michael Jackson"),
  Movie(name: "The Dark Knight", director: "Christopher Nolan"),
]

for item in library {
  if let movie = item as? Movie {
    print("Movie: \(movie.name), Director: \(movie.director)")
  } else if let song = item as? Song {
    print("Song: \(song.name), Artist: \(song.artist)")
  }
}

In this example, you have a base class MediaItem with a single property name and a Song and Movie class that both inherit from MediaItem. Song adds an additional artist property, and Movie adds a director property.

Then you create an array of library with a mix of Song and Movie instances.

Finally, you use a for-loop to iterate over the library array and downcast each MediaItem instance to either a Song or a Movie using the as? operator. If the downcast is successful, print the details of the Song or Movie instance, otherwise, skip the item.

This code outputs:

Song: Never Gonna Give You Up, Artist: Rick Astley
Movie: The Matrix, Director: Wachowski
Song: Smooth Criminal, Artist: Michael Jackson
Movie: Inception, Director: Christopher Nolan
Song: Billie Jean, Artist: Michael Jackson
Movie: The Dark Knight, Director: Christopher Nolan

Upcasting in Swift

Using the same classes, here is an example on Upcasting:

let song = Song(name: "Shake it Off", artist: "Taylor Swift")
let movie = Movie(name: "Avatar", director: "James Cameron")

var library = [song, movie]

// Upcasting
for item in library {
  if let mediaItem = item as? MediaItem {
    print("Media item: \(mediaItem.name)")
  }
}

In this example, song and movie instances are cast to MediaItem, so that they can be stored in a library array which only holds MediaItem objects. This is an example of upcasting, where a subclass type is converted to its superclass type.

© 2024 Kodeco Inc.