0

Introduction à la programmation orientée objet

Salut tout le monde ! La dernière fois en décortiquant la structure d’un app iOS, on a parlé de classes dans le code. Eh bien il est temps de savoir un peu de quoi il s’agit et de comprendre comment ça marche. Si vous perdez un peu le nord, n’hésitez pas à relire l’article sur les fonctions avant de vous attaquer à celui-là, sinon à vos boussoles, on va s’orienter sur cette étape indispensable.

Le principe

Le principe de la POO (programmation orientée objet) et de définir dans le code des classes qui sont des objets contenant des fonctions et des variables qui lui sont propres. Par exemple, on pourrait imaginer un objet “Personnage” (dans un jeu) dans le code qui comprendrait plusieurs choses :

Objet Personnage
  • Variables
    • nom - le nom du personnage
    • pts_vie - le nombre de point de vie actuel du personnage
    • position - la position du personnage su la carte
    • attaque - le nombre de points de dégâts fait par son attaque
  • Fonctions
    • seDeplacer() - la fonction pour déplacer le personnage
    • attaquer() - la fonction effectuant une attaque
    • subiAttaque() - la fonction exécutée quand le personnage se fait attaquer

On regroupe ainsi dans un même bloc (un objet !) tout le code qui le concerne. Cela a plusieurs avantages non négligeables concernant l’organisation et la clarté de son code, mais cela permet aussi de pouvoir se servir plusieurs fois du même code en simultané et dans la même app sans avoir à le réécrire. Si on utilisait notre classe Personnage dans un jeu, on pourrait déclarer tous les personnages du jeu simplement avec un appel à notre classe.

Le code

Voyons tout ça avec du Swift, parce que je pense que ce sera plus clair à comprendre avec du vrai code (curieusement…). Déclarons notre personnage dans un playground Swift (iOS ou mac) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Personnage {
    var nom : String = "Bobby"
    var pts_vie : Int = 20
    var position : [Int] = [0, 0]
    var attaque : Int = 3
   
    func seDeplacer() {
        print("Déplacement")
    }
   
    func attaquer() {
        print("Attaquer")
    }
   
    func subiAttaque() {
        print("Attaque reçue")
    }
}

Les plus malins auront remarqué que le nom de la classe est écrit avec un majuscule au début, contrairement au noms de variables et de fonctions. C’est pour pouvoir les différencier lorsqu’on s’en sert dans le code. On verra dans un autre articles les bonnes pratiques de nomenclature en Swift. C’est d’ailleurs parce que ce sont des classes que les types par défaut des variables commencent tous par une majuscule (String, Int, Double…)

Tout ce code est inerte, c’est à dire qu’il ne s’exécutera pas tout seul de haut en bas comme on en a l’habitude. C’est plutôt comme un morceau de code autonome stocké là dont on peut se servir très facilement en l’appelant comme une fonction :

1
let personnage = Personnage()

A la différence qu’on ne stocke pas le résultat de la fonction dans la variable, mais le bloc de code lui-même. On peut ensuite accéder aux différentes composantes de l’objet en juxtaposant un point “.” à la suite de la variable puis en nommant la variable ou la fonction désirée :

1
2
3
4
let personnage = Personnage()

print(personnage.nom)    // Bobby
personnage.seDeplacer()  // Déplacement

On peut donc disposer d’objets indépendants et autonomes dans notre code que l’on peut réutiliser à volonté. On peut dans cet exemple déclarer plusieurs personnages qui auront tous les mêmes actions mais qui agiront indépendamment les uns des autres. On peut même les stocker dans un tableau par exemple :

1
2
3
4
5
let pierre = Personnage()
let paul = Personnage()
let jacques = Personnage()

var personnages : [Personnage] = [pierre, paul, jacques]

Le type d’une classe par défaut est son nom, mais on verra plus tard qu’elle peut hériter d’autres types.

L’initialisation

Le problème qui se pose dans notre exemple, c’est qu’ici les trois variables différentes contiennent en fait toutes le même contenu. Par exemple si l’on souhaite lire le nom de paul, ce sera “Bobby” car c’est ce qui est défini par défaut dans notre classe. On peut bien sur le modifier comme une variable standard :

1
2
3
4
5
let pierre = Personnage()
print(pierre.nom) // Bobby

pierre.nom = "Pierre"
print(pierre.nom) // Pierre

Notons d’ailleurs que l’on peut modifier librement les variables contenues dans notre classe même si celle-ci est stockée dans une constante (let).

Mais ceci n’est pas très pratique, car il faut penser à chaque fois que l’on déclare une nouveau Personnage à modifier son nom juste après ou bien il s’appellera Bobby. On pourrait bien sûr stocker par défaut un String vide dans la variable, mais cela ne résoudrai pas le problème de devoir effectuer la modification à chaque nouvelle déclaration.

On va donc pouvoir définir des variables qui n’ont pas de contenu tant que la classe n’est pas déclarée, elle ne contiendront pas de valeur par défaut. Pour cela rien de plus simple, il suffit de ne pas leur attribuer de valeur lors de leur déclaration :

1
2
3
4
5
6
class Personnage {
    var nom : String
    var pts_vie : Int = 20

    // etc...
}

Mais si on laisse la classe telle quelle, Xcode nous retournera une erreur Class ‘Personnage’ has no initializers comme quoi la classe n’a pas toutes ses variables initialisées. On va donc déclarer une fonction particulière qui va s’exécuter lors de l’initialisation de la classe : init()

1
2
3
4
5
6
7
8
9
10
11
12
class Personnage {
    var nom : String
    var pts_vie : Int = 20
    var position : [Int] = [0, 0]
    var attaque : Int = 3

    init(nom _nom : String) {
        nom = _nom
    }

    // etc...
}

Le mot-clé func n’est pas requis pour cette fonction car elle occupe une place unique dans la classe et est interprétée différemment par le compilateur

De cette façon on pourra définir le nom de chaque personnage lors de leur déclaration, simplement en passant le paramètre “nom” à la classe :

1
2
3
let pierre = Personnage(nom: "Pierre")
let paul = Personnage(nom: "Paul")
let jacques = Personnage(nom: "Jacques")

Il ne sera en revanche plus possible d’initialiser la classe sans ce paramètre, pour ce faire on doit déclarer une autre instance de init() sans paramètres, qui définisse une valeur par défaut de la variable nom :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Personnage {
    var nom : String
    var pts_vie : Int = 20
    var position : [Int] = [0, 0]
    var attaque : Int = 3
   
    init(nom _nom : String) {
        nom = _nom
    }
   
    init() {
        nom = "Bobby"
    }
   
    // etc...
}

let bobby = Personnage()
let pierre = Personnage(nom: "Pierre")
let paul = Personnage(nom: "Paul")
let jacques = Personnage(nom: "Jacques")

 

Toujours là ? Bon on commence à avoir ce qu’il faut (et là où il faut) pour faire des scripts complexes et bien les organiser. On va s’arrêter là pour aujourd’hui, ne vous en faites pas on va y revenir très bientôt car c’est loin d’être tout ce qu’il y a à savoir sur ce mastodonte qu’est la POO ! Je vous dis donc à bientôt les amis 😉

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *