Mis à jour le 30/10/2017
  • 20 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

J'ai tout compris !

Gérez vos types

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Il existe un moyen avec Swift de vérifier le type d’une instance. On va alors pouvoir jouer ici sur les classes héritées et les classes mères.

On sait qu’une classe héritée est forcément du type de sa mère : il peut alors être de deux types différents (Une classe Chien peut être de classe Chien et Animal par exemple). Mais comment savoir pour une classe mère si elle peut être d’un type d’une classe fille précise ? Et comment faire pour considérer une classe mère en tant que classe fille ? C’est ce que nous allons voir maintenant.

Préparons le terrain

Pour vous expliquer tout ça, je vais m’appuyer sur la documentation d’Apple qui nous propose un exemple très pertinent.

Nous allons imaginer que nous disposons d’une bibliothèque qui se comporte de chansons et de films. Une chanson et un film sont tous les deux des médias. Transposons cela en code Swift (allez c’est facile pour nous maintenant tout ça :p ).

class Media {
    var nom: String
    
    init(nom: String) {
        self.nom = nom
    }
}
 
class Chanson : Media {
    var chanteur: String
    
    init(nom: String, chanteur: String) {
        self.chanteur = chanteur
        super.init(nom: nom)
    }
}
 
class Film : Media {
    var directeur: String
    
    init(nom: String, directeur: String) {
        self.directeur = directeur
        super.init(nom: nom)
    }
}
 
// Construction d'une bibliothèque
let bibliotheque: [Media] = [
    Film(nom: "Casablanca", directeur: "Michael Curtiz"),
    Chanson(nom: "Blue Suede Shoes", chanteur: "Elvis Presley"),
    Film(nom: "Citizen Kane", directeur: "Orson Welles"),
    Chanson(nom: "The One And Only", chanteur: "Chesney Hawkes"),
    Chanson(nom: "Never Gonna Give You Up", chanteur: "Rick Astley")
]

Vérifier un type

Pour vérifier si un type est de type  Chanson  ou de type  Film  , nous allons utiliser le mot-clé  is  . Ce mot-clé renverra  true  si le type est vérifié comme l’on souhaite,  false  dans le cas contraire.

Maintenant, pour bien comprendre et pour utiliser  is  , comptons le nombre de chansons et de films au sein de notre bibliothèque.

var nombreChansons: Int = 0
var nombreFilms: Int = 0
 
for media in bibliotheque {
    if media is Chanson {
        nombreChansons += 1
    } else if media is Film {
        nombreFilms += 1
    }
}
 
print("Il y a \(nombreChansons) chansons et \(nombreFilms) films dans notre bibliothèque.")

Cet exemple parcourt chaque  media  de notre bibliothèque. Pour chaque  media  , on vient regarder de quel type il est et on incrémente la variable qui correspond au type.

La condition est assez simple à lire, en français cela pourrait donner par exemple : « Si le média est de type Chanson alors ».

Changer le type d’une classe mère par une classe fille

Pour changer le type d’une classe mère par celui de sa classe fille, nous allons utiliser le mot-clé  as  .  as  prendra toutefois deux tournures :  as?  quand nous ne seront pas sûr du type de la variable,  as!  quand nous serons sûr cette fois-ci. Pour changer le type, nous allons vérifier par une condition que le changement peut se réaliser. Et oui, on ne peut pas dire d’une chanson que c’est un film et vice versa ! On va donc tenter de créer une nouvelle variable qui comprendra notre chanson ou notre film si cela réussi.

Pour comprendre tout ça et vous montrer un exemple, imaginons que cette fois-ci nous voulons afficher les détails des médias de notre bibliothèque. On veut connaitre le nom et le chanteur de la chanson et on veut connaitre le nom et le directeur du film.

for media in bibliotheque {
    if let chanson = media as? Chanson {
        print("Chanson ayant pour nom '\(chanson.nom)' et pour chanteur '\(chanson.chanteur)'.")
    } else if let film = media as? Film {
        print("Film ayant pour nom '\(film.nom)' et pour directeur '\(film.directeur)'.")
    }
}

Types non spécifiques

Il est possible de travailler sur des types non spécifiques. C’est-à-dire des types qui seront les classes mères de tout vos types grosso modo.

Pour cela, nous avons :

  • Any  qui peut représenter une instance de n’importe quel type (y compris des fonctions)

  • AnyObject  qui lui peut représenter une instance de n’importe quel type de classe

Voici un exemple d’utilisation de  Any  qui va nous permettre de remplir un tableau de… n’importe quoi en fait ! :D

var nimporteKoi: [Any] = []

nimporteKoi.append(0)
nimporteKoi.append(1.2)
nimporteKoi.append(34)
nimporteKoi.append(5.6789)
nimporteKoi.append("dix")
nimporteKoi.append((11, 12))
nimporteKoi.append(Film(nom: "Casablanca", directeur: "Michael Curtiz »))
// …

Et voilà, une petite astuce qui peut faire la différence un jour dans votre code. ;)

Pour pouvoir récupérer les valeurs et vous en servir, servez-vous de  as?  comme vu ci-dessus :

if let entier = nimporteKoi[0] as? Int {
    print(entier)
}

Pour résumer

  • is  permet de vérifier le type, il renvoie true ou false

  • as?  permet de changer le type d’une classe mère par celle de sa classe fille

  • as!  permet la même chose que  as?  seulement si l’on est sûr du type attendu

  • Any  peut représenter une instance de n’importe quel type

  • AnyObject  peut représenter une instance de n’importe quel type de classe

Exemple de certificat de réussite
Exemple de certificat de réussite