Conversion de type en Swift

La conversion de type (cast en anglais) est un moyen de vérifier le type d’une instance ou de traiter cette instance comme une super-classe ou une sous-classe de sa hiérarchie. Pour cela en Swift il y a 2 mots clés is et as. Ce cours va vous montrer aux travers d’exemple comme la conversion de type fonctionne en Swift.

Définition d’une hiérarchie de classe

Afin d’avoir des examples sur lesquelles s’appuyer lors de ce cours nous allons créer une hiérarchie de classe. Pour cela on va créer un véhicule comme super-classe qui contient une seule propriété et un initialiser :

class Véhicule {
  let marque: String

  init(marque: String) {
    self.marque = marque
  }
}

Un véhicule est un engin d’une certaine marque représenté ici par la propriété marque qui est initialisé grâce à son initialiseur. Maintenant nous allons définir 2 autres types de véhicule : un vélo et une voiture. Ces 2 types vont hériter de Véhicule et vont ajouter des propriétés spécifique à chacun :

class Voiture: Véhicule {
  let nombreDePorte: UInt

  init(marque: String, nombreDePorte: UInt) {
    self.nombreDePorte = nombreDePorte

    super.init(marque: marque)
  }
}

class Vélo: Véhicule {
  let toutTerrain: Bool

  init(marque: String, toutTerrain: Bool) {
    self.toutTerrain = toutTerrain

    super.init(marque: marque)
  }
}

Une Voiture contient comme propriété le nombre de porte nombreDePorte tandis que le Vélo lui possède une propriété pour savoir si il est tout terrain toutTerrain. Maintenant nous allons créer un garage qui est cimplement une liste de véhicule :

let garage: [Véhicule] = [
  Voiture(marque: "Renault Clio IV", nombreDePorte: 5),
  Vélo(marque: "Polygon", toutTerrain: true),
  Voiture(marque: "BMW Mini", nombreDePorte: 3),
  Vélo(marque: "B'Twin", toutTerrain: false)
]

Maintenant que notre cadre est bien poser nous allons nous atteler au coeur du sujet.

Vérification de type

Pour vérifier les types en Swift il faut utiliser l’opérateur is. Cet opérateur retourne simplement un booléen en fonction du résultat :

  • true : l’instance est bien du type donné
  • false : l’instance est d’un autre type

Dans l’example ci-dessous nous allons compter le nombre d’occurence de chaque type de véhicule présent dans le garage :

var nombreDeVoiture = 0
var nombreDeVélo    = 0

for véhicule in garage {
  switch véhicule {
  case is Voiture:
    nombreDeVoiture++
  case is Vélo:
    nombreDeVélo++
  default:
    break
  }
}

print("\(nombreDeVoiture) voitures et \(nombreDeVélo) vélos")
// Affiche : 2 voitures et 2 vélos

Dans cet example nous itérons au travers de notre garage et en fonction du type de véhicule nous incrémentons la variable correspondante. Si vous n’êtes pas familier de la structure de contrôle switch je vous conseil cet article.

La coercition descendante (Downcasting)

Une constante ou une variable d’un certain type peut en réalité se référer à un sous-type de la classe donné. Et quand vous en avez besoin vous pouvez essayer de downcaster vers cette sous classe en utilisant les opérateurs as? ou as!.

Le downcasting pouvant échouer l’opérateur de conversion de type est fournit sous 2 différentes formes. La forme conditionnel avec as? qui retourne une valeur optionnelle du type vers lequel on essaye de le convertir. La seconde forme est le as! qui lui va forcer la conversion au risque de faire planter le programme si le type donné ne peut pas être convertis.

Dans l’example ci-dessous nous allons itérer sur chaque véhicule du garage et afficher la description approprié :

for véhicule in garage {
  if let voiture = véhicule as? Voiture {
    print("Voiture \(voiture.nombreDePorte) de \(voiture.marque)")
  }
  else if let vélo = véhicule as? Vélo {
    print("Vélo \(vélo.toutTerrain) de \(vélo.marque)")
  }
}

//    Voiture 5 de Renault Clio IV
//    Vélo true de Polygon
//    Voiture 3 de BMW Mini
//    Vélo false de B'Twin

Dans cet example nous essayons de downcaster les véhicules vers des Voiture et des Vélo. Comme véhicule est de type Véhicule il est possible que le véhicule soit l’un des sous-types. Mais comme on ne connait pas à l’avance les sous-types des variables on essaye de convertire celle-ci en utilisant l’opérateur as?. La condition dans les if essaye d’accéder au véhicule en tant que Voiture ou Vélo et si il y arrive de créer une variable temporaire du type correspondant que l’on peut utiliser ensuite dans le sous bloc de code.

Conversion de type pour les Any et AnyObject

Swift fournit deux alias de type spéciaux pour travailler avec des types non spécifique :

  • AnyObject : il peut représenter une instance de n’importe quelle classe.
  • Any : il peut représenter une instance de n’importe quel type (classe, struct, enum et fonction).

Quand vous utilisez des APIs de Cocoa il est fréquent de recevoir des listes de type [AnyObject]. Cependant il est fréquent que l’on connaisse par avance le contenu de ces listes ou de ces objets. L’example ci dessous définis une liste de type [AnyObject] dont on sait qu’ils contiennent uniquement des Voiture :

let objets: [AnyObject] = [
  Voiture(marque: "Renault Clio IV", nombreDePorte: 5),
  Voiture(marque: "BMW Mini", nombreDePorte: 3)
]

for voiture in objets as! [Voiture] {
  print("Voiture \(voiture.nombreDePorte) de \(voiture.marque)")
}

//    Voiture 5 de Renault Clio IV
//    Voiture 3 de BMW Mini

Dans cet example comme on connait les types contenu dans la liste on peut caster la liste en [Voiture] en utilisant l’opérateur as!.

Conclusion

J’espère que maintenant vous comprenez mieux le fonctionnement de la conversion de type en swift. Pour récapituler il y a 3 opérateurs à retenir qui sont is, as? et as! qui servent respectivement à vérifier les types, à downcaster avec une vérification et à forcer le downcast.

1 Etoile2 Etoiles3 Etoiles4 Etoiles5 Etoiles (3 votes, average: 3,67 out of 5)
Loading...

Aucun commentaire

Time limit is exhausted. Please reload CAPTCHA.

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.