Mis à jour le lundi 30 octobre 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 !

Les extensions

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

Une extension en Swift va vous permettre d’augmenter la capacité de vos types, c'est-à-dire que vous allez pouvoir ajouter de nouveaux propriétés ou méthodes à une classe déjà existante.

Cette notion est intéressante dans le cas où il s'agit d'une classe qui ne vous appartient pas et que vous ne voulez absolument pas toucher pour une raison ou un autre. Ou alors, tout simplement car vous ne disposez pas de cette classe, vous n'y avez pas accès. Et j'entends par là les classes déjà existantes au sein de votre projet proposé par Swift comme StringIntDoubleBool, etc.

Les extensions

Ce que vous pouvez concrètement faire grâce aux extensions en Swift :

  • Ajouter de nouvelles propriétés. Vous pourrez reprendre la valeur d'une propriété existante et la modifier à votre guise.

  • Ajouter de nouvelles méthodes. 

  • Ajouter de nouveaux constructeurs.

J'attire votre attention sur le fait qu'une extension ne vous permettra que d'ajouter de nouvelles fonctionnalités à un type. En aucun cas vous ne pourrez remplacer les fonctionnalités déjà existantes. ;)

Syntaxe d'une extension

Pour utiliser une extension, nous allons utiliser le mot cléextension. Le nom à fournir à votre extension sera le nom du type à étendre (donc le nom de votre classe par exemple).

extension NomDuTypeAEtendre {
    // Définitions des nouvelles fonctionnalités ici   
}

Une extension peut aussi adopter un ou plusieurs protocoles. 

extension NomDuTypeAEtendre: Protocole1, Protocole2 {
    // Implémenter vos protocoles et ajouter vos nouvelles fonctionnalités
}

Ajouter de nouvelles propriétés

Pour ajouter de nouvelles propriétés voici la syntaxe à respecter pour étendre par exemple le type Int  :

extension Int {
    var nomPropriete: Type { return valeurARetourner }   
}

Mais il faut que je vous parle à nouveaux du mot-clé self  ici qui peut être utilisable.

Déclarer de nouvelles propriétés est surtout sympa quand on agit sur la valeur actuelle du type. Par exemple, si on souhaite accéder à une propriété de type Int, ce serait bien que cette nouvelle propriété vous donne par exemple le carré de la valeur de ce Int, ou encore la valeur multipliée par 10.

Grâce au mot-clé self, vous pourrez accéder à la valeur actuelle dans la nouvelle propriété et jouer avec elle. L'exemple ci-dessous vous permettra de mieux comprendre ce que je viens de dire :

extension Int {
    var carre: Int { return self * self }
    var fois10: Int { return self * 10 }
}

print(2.carre)
print(7.fois10)

Vous pouvez directement accéder à votre nouvelle propriété juste après votre nombre (à condition ici que le nombre soit de type Int). Je l'ai expliqué dans le chapitre précédent, unInt est un objet. Donc rien ne vous empêche d'accéder aux propriétés et méthodes directement de cette façon. Vous auriez néanmoins pu faire comme ceci :

extension Int {
    var carre: Int { return self * self }
    var fois10: Int { return self * 10 }
}

var nombre: Int = 2
print(nombre.carre)
print(nombre.fois10)

// On peut aussi faire cela avec type différent de Int
print(Int("123")!)

Si je retourne à mon autre exemple, 2 ou 7 seront les valeurs. Donc, ce que contiendra self.. Sauf qu'en faisant par exemple 2.carre on n'affichera pas 2 mais ce que retourne la propriété pour ce nombre 2, c'est-à-dire 2 * 2 soit 4.

La documentation d'Apple sur Swift propose un exemple assez intéressant aussi :

extension Int {
    var m: Int { return self }
    var mm: Int { return self * 1000 }
    var cm: Int { return self * 100 }
    var dm: Int { return self * 10 }
}

print("2m vaut \(2.cm)cm")
var nouvelleValeurEnMetres = 2.m + 1.dm + 7.cm + 12.mm

Vous pouvez convertir plus facilement vos nombres sans forcément passer par une méthode. 11

Ajouter un nouveau constructeur

On va prendre pour exemple deux structures (les constructeurs sont définis par défaut grâce aux propriétés donc). On va réaliser une structureSegment qui prendra comme propriétés deux coordonnées. Le point de départ du segment sur un graphe, et le point d'arrivée sur un graphe. On réalisera aussi une structureCoordonnees qui permettra de donner le point d'abscisse et le point d'ordonnée.

struct Coordonnees {
    var x: Double
    var y: Double
}

struct Segment {
    var c1: Coordonnees
    var c2: Coordonnees
}

On définit donc un segment comme ceci :

Segment(c1: Coordonnees(x: 1.0, y: 1.0), c2: Coordonnees(x: 4.0, y: 4.0))

On pourrait alors imaginer un nouveau constructeur qui prendrait un à un les valeurs des points d'abscisses et des points d'ordonnées de chacun des deux points.

struct Coordonnees {
    var x: Double
    var y: Double
}

struct Segment {
    var c1: Coordonnees
    var c2: Coordonnees
}

extension Segment {
    init(x1: Double, y1: Double, x2: Double, y2: Double) {
        self.init(c1: Coordonnees(x: x1, y: y1), c2: Coordonnees(x: x2, y: y2))
    }
}

// Deux définitions différentes d'un segment
Segment(c1: Coordonnees(x: 1.0, y: 1.0), c2: Coordonnees(x: 4.0, y: 4.0))
Segment(x1: 1.0, y1: 1.0, x2: 4.0, y2: 4.0)

Ajouter de nouvelles méthodes 

On pourrait s'imaginer ici d'ajouter plein de fonctions à attribuer à un type nombre. Par exemple, définir le carré d'un nombre, son cube, etc.11

extension Int {
    func carre() -> Int {
        return self * self
    }
    
    func cube() -> Int {
        return self * self * self
    }
    
    func afficheCarreEtCube() {
        print("\(self.carre()), \(self.cube())")
    }
}

5.afficheCarreEtCube()
print(4.cube())

Rien d'autre à ajouter. Vous agissez comme si vous étiez à l'intérieur de la classe, mais sans vraiment y être au final. :) 

Pour résumer 

  • On peut ajouter de nouveaux propriétés et méthodes à une classe, structure ou énumération grâce au mot-clé extension.

  • Le mot-clé self permet d'accéder à la valeur actuelle.

  • On peut aussi définir de nouveaux constructeurs.

  • Nous ne pouvons pas ajouter des fonctionnalités déjà existantes.

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