Vous pouvez utiliser la conversion de type avec une hiérarchie de classes et de sous-classes pour vérifier le type d'une instance de classe particulière et pour convertir cette instance en une autre classe au sein de la même hiérarchie.


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

L'extrait suivant définit deux sous-classes de MediaItem. Les sous-classes contiennent des informations supplémentaires sur un film ou une chanson.


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)
    }
}

L'extrait final crée un tableau de constantes appelé library, qui contient deux instances Movie et trois instances Song. Le type du tableau est déduit en l'initialisant avec le contenu d'un littéral de tableau. Le vérificateur de type de Swift est capable de le déduire :


let library = [
    Movie(name: "Casablanca", director: "Michael Curtiz"),
    Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
    Movie(name: "Citizen Kane", director: "Orson Welles"),
    Song(name: "The One And Only", artist: "Chesney Hawkes"),
    Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
]
// the type of "library" is inferred to be [MediaItem]

Si vous parcourez le contenu de ce tableau, les éléments que vous recevez sont de type MediaItem, et non en tant que Movie ou Song.

Vérifier le type d'une instance

Utilisez l'opérateur de vérification de type is pour vérifier si une instance est d'un certain type de sous-classe. L'opérateur de vérification de type renvoie true si l'instance est de ce type de sous-classe et false si ce n'est pas le cas.


var movieCount = 0
var songCount = 0

for item in library {
    if item is Movie {
        movieCount += 1
    } else if item is Song {
        songCount += 1
    }
}

print("Library have \(movieCount) movies and \(songCount) songs")
// Prints "Library have 2 movies and 3 songs"

Conversion

L'exemple ci-dessous itère sur chaque MediaItem dans library et imprime une description appropriée pour chaque élément. Pour ce faire, il doit accéder à chaque élément en tant que Movie ou Song, et pas seulement en tant que fichier MediaItem. Ceci est nécessaire pour qu'il puisse accéder à la propriété director ou artist d'un Movie ou Song pour une utilisation dans la description.


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

// Movie: Casablanca, dir. Michael Curtiz
// Song: Blue Suede Shoes, by Elvis Presley
// Movie: Citizen Kane, dir. Orson Welles
// Song: The One And Only, by Chesney Hawkes
// Song: Never Gonna Give You Up, by Rick Astley
En raison de l'incertitude, la forme de l'opérateur de conversion de type as? renvoie une valeur facultative lors d'une tentative de conversion descendante vers un type de sous-classe. Type optionnel.

Type non spécifique Any et AnyObject

Swift propose deux types spéciaux pour travailler avec des types non spécifiques :

  • Any peut représenter une instance de n'importe quel type, y compris les types de fonctions.
  • AnyObject peut représenter une instance de n'importe quel type de classes.

var things = [Any]()

things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append((3.0, 5.0))
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
things.append({ (name: String) -> String in "Hello, \(name)" })

Le tableau things contient deux valeurs Int, deux valeurs Double, une valeur String, un tuple de type (Double, Double), le film "Ghostbusters" et une expression de clôture qui prend une valeur String et renvoie à une autre valeur String.

Le type Any représente des valeurs de tous types, y compris les types facultatifs.

Pour découvrir le type spécifique d'une constante ou d'une variable connue uniquement pour être de type Any ou AnyObject, vous pouvez utiliser un modèle is ou as dans Switch. L'exemple ci-dessous itère les éléments du tableau things et interroge le type de chaque élément avec une instruction switch.

 
for thing in things {
    switch thing {
    case 0 as Int:
        print("zero as an Int")
    case 0 as Double:
        print("zero as a Double")
    case let someInt as Int:
        print("an integer value of \(someInt)")
    case let someDouble as Double where someDouble > 0:
        print("a positive double value of \(someDouble)")
    case is Double:
        print("some other double value that I don't want to print")
    case let someString as String:
        print("a string value of \"\(someString)\"")
    case let (x, y) as (Double, Double):
        print("an (x, y) point at \(x), \(y)")
    case let movie as Movie:
        print("a movie called \(movie.name), dir. \(movie.director)")
    case let stringConverter as (String) -> String:
        print(stringConverter("Michael"))
    default:
        print("something else")
    }
}

// zero as an Int
// zero as a Double
// an integer value of 42
// a positive double value of 3.14159
// a string value of "hello"
// an (x, y) point at 3.0, 5.0
// a movie called Ghostbusters, dir. Ivan Reitman
// Hello, Michael