Après les fonctions et closures, attaquons un sujet passionnant dont tu auras besoin au quotidien. En effet, les classes et structures ont des fonctions relativement similaires. Elles permettent toutes les deux de créer un objet à partir d’un schéma donné, c’est ce qu’on appelle la programmation orientée objet. Toutes les instances de cet objets auront donc la même forme. Mais tu vas voir qu’il existe quand même quelques petites différences notables.

Contrairement à d’autres langages de programmation, Swift ne nous oblige pas à créer des fichiers d’interface et d’implémentation distincts pour les structures et les classes. On définit une structure ou une classe dans un seul fichier, et l’interface externe de cette classe ou de cette structure est automatiquement mise à la disposition des autres fichiers.

Tu connais déjà un peu la tête des classes et des structures ? Va directement voir leurs différences.

Classes

Elle permettent de créer des objets uniques selon un certain schéma. Elles s’écrivent toujours avec une majuscule car en définissant une nouvelle classe, tu définis un nouveau type Swift.

class Fruit {
    var name: String
    var season: String
    var isFrench = false
    
    init(name: String, season: String, isFrench: Bool) {
        self.name = name
        self.season = season
        self.isFrench = isFrench
    }
}

Le corps de la classe doit contenir un initialiser (ou constructeur) qui définira les paramètres à renseigner pour créer un objet de cette classe. Il est construit avec le mot clé init.

Voici la syntaxe pour créer une instance :

let favFruit = Fruit(name: "Fraise", season: "été", isFrench: true)

Pour accéder aux propriétés de la classe on utilise le . juste après la variable :

favFruit.name = "melon"
print("La saison du \(favFruit.name) est \(favFruit.season)") 
//Affiche "La saison du melon est été"

Structures

Elles sont similaires, vois plutôt :

struct Gauge {
    var width = 0
    var height = 0
}

let knitGauge = Gauge(width: 10, height: 10)

print("L'échantillon de mon tricot est de \(knitGauge.width) sur \(knitGauge.height).")

Principales différences

Maintenant qu’on a vu la manière de construire les classes et structures, étudions leurs différences.

Leurs types

  • Une classe est un type de référence = plutôt qu’une copie, c’est une référence à la même instance existante qui est utilisée. C’est à dire que si la valeur initiale de la première variable change, la valeur de la deuxième changera.
class Person {
    var name: String
    var age: Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

var alice = Person(name: "Alice", age: 30)
var person2 = alice // Création d'une référence à l'objet person1

person2.age = 31
print(alice.age) // Affiche 31 car person2 est une référence à alice

  • Une structure est un type de valeur = la valeur est copiée lorsqu’elle est affectée à une variable ou à une constante, ou lorsqu’elle est passée à une fonction. C’est à dire que la valeur, lorsqu’elle a été copiée dans une nouvelle variable, ne pourra pas changer. Il en est de même pour les énumérations.
struct Point {
    var x: Int
    var y: Int
}

var point1 = Point(x: 1, y: 2)
var point2 = point1 // Création d'une copie de point1

point2.x = 3
print(point1.x) // Affiche 1 car point2 est une copie de point1

Héritage

Les classes peuvent hériter d’autres classes.

class Animal {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func makeSound() {
        print("L'animal fait un son.")
    }
}

class Dog: Animal {
    override func makeSound() {
        print("Le chien aboie.")
    }
}

let animal = Animal(name: "Generic animal")
let dog = Dog(name: "Fido")

animal.makeSound() // Affiche "L'animal fait un son."
dog.makeSound() // Affiche "Le chien aboie."

La sous-classe Dog hérite des propriétés de la classe principale Animal. Dans cet exemple, nous surchargeons la méthode makeSound() en fonction de l’animal.

Pour les structures (structs), on a vu qu’elles ne prenaient pas en charge l’héritage car elles sont des types de valeur. Cependant, les structs peuvent implémenter des protocoles, ce qui leur permet de bénéficier de la polymorphie. Cela signifie qu’une struct peut se comporter comme un autre type en implémentant les mêmes méthodes et propriétés que le type, même s’il ne s’agit pas d’une sous-classe directe.

Nous reviendrons plus en détail sur les protocols dans un article prochain.

Destructeurs

Les classes ont la possibilité de définir des destructeurs, tandis que les structures n’ont pas cette fonctionnalité. Ils sont crées avec le mot clé deinit.

Les destructeurs sont des méthodes spéciales qui sont appelées automatiquement lorsque l’objet d’une classe est supprimé de la mémoire.

class MyClass {
    var name: String
    
    init(name: String) {
        self.name = name
        print("Je créé une instance de ma classe \(name)")
    }
    
    deinit {
        print("Je détruis l'instance de ma classe \(name)")
    }
}

var myObject: MyClass? = MyClass(name: "Test") // Création de l'objet
// Affiche "Je créé une instance de ma classe Test"
myObject = nil // Destruction de l'objet
// Affiche "Je détruis l'instance de ma classe Test"


Te voilà un peu plus au clair sur la différence qu’il existe entre une classe et une structure. On se retrouve bientôt pour parler des types optionels, il y a plein de choses à dire dessus !

Dis nous en commentaire ce que tu voudrais retrouver comme doc sur Swift ✌️

Si tu as aimé cet article, partage le 🫶