Gérer la visibilité des membres de classe en Python orienté objet

Dans cette nouvelle leçon liée à l’orienté objet, nous allons voir un autre concept important de la POO qui concerne l visibilité ou le niveau d’accès des différents membres de classe.

Nous terminerons cette leçon avec un petit rappel sur “pourquoi coder en orienté objet” qui, je l’espère, vous permettra de commencer à avoir une vision d’ensemble claire sur la programmation orientée objet et sur ses objectifs.

 

Les niveaux de visibilité des membres de classe en programmation orientée objet

Dans la plupart des langages qui supportent l’orienté objet, on peut définir des “niveaux de visibilité” ou “niveaux d’accès” pour les membres des classes (c’est-à-dire pour les variables et les fonctions).

En POO, on distingue généralement trois niveaux de visibilité différents :

  • Les membres privés auxquels on ne peut accéder que depuis l’intérieur de lac classe ;
  • Les membres protégés auxquels on ne peut accéder que depuis l’intérieur de la classe ou depuis une classe fille ;
  • Les membres publics auxquels on peut accéder depuis n’importe quelle instance (ou objet) de la classe ou d’une classe fille.

Ces niveaux de visibilité permettent de “protéger” certains membres de classes qui ne devraient pas être modifiés dans n’importe quelle situation ou depuis n’importe quel endroit.

 

Les niveaux de visibilité des membres de classe en Python

Python n’implémente pas directement ces concepts de visibilité des membres de classe et il est donc impossible de définir un membre comme privé ou protégé : par défaut, tous les membres de classe sont publics en Python.

En revanche, certaines conventions ont été mises en place par la communauté Python, notamment au niveau des noms des membres de classe qui servent à indiquer aux autres développeurs qu’on ne devrait accéder à tel membre que depuis l’intérieur de la classe ou à tel autre membre que depuis la classe ou une classe fille.

Attention ici : ce ne sont que des conventions qui n’ont aucun équivalent réel en Python : on va pouvoir informer d’autres développeurs du niveau de visibilité souhaité pour un membre mais tous les membres seront toujours publics en Python et il est de la responsabilité des autres développeurs de suivre nos indications ou pas.

Ces conventions sont les suivantes :

  • On préfixera les noms des membres qu’on souhaite définir comme “privés” avec deux underscores comme ceci : __nom-du-membre ;
  • On préfixera les noms des membres qu’on souhaite définir comme “protégés” avec un underscore comme ceci : _nom-du-membre.

Il est à noter que ces conventions n’ont pas été adoptées par hasard. En effet, Python possède un mécanisme appelé “name mangling” qui fait que tout membre de classe commençant par deux underscores, c’est-à-dire de la forme __nom-du-membre sera remplacé textuellement lors de l’interprétation par _nom-de-classe__nom-du-membre.

Cela fait que si un développeur essaie d’utiliser un membre défini avec deux underscores tel quel, Python renverra une erreur puisqu’il préfixera le nom avec un underscore et le nom de la classe du membre.

Cette règle a été prévue par Python pour éviter les accidents de conflits entre plusieurs membres de plusieurs classes qui auraient le même nom. Elle n’empêche pas d’accéder ou de modifier un membre “privé”. En effet, il suffit de préfixer le membre de la même façon que Python lors de son interprétation pour y accéder.

Prenons immédiatement un exemple afin de bien comprendre ce qu’on vient de dire :

Définition variables de classe public, protected et private en Python orienté objet

On définit ici une classe Visibilite qui contient trois variables public, _protected et __private. Notez qu’on pourrait aussi bien définir des fonctions de la même manière.

Maintenant, créons un objet à partir de cette classe et essayons d’afficher les valeurs de nos variables de classe à partir de l’objet créé :

Accès aux variables de classe protected et private en Python orienté objet

Comme vous le voyez, on accède sans souci à nos variables public et _protected. En revanche, pour __private, le mécanisme de name mangling s’active et le nom passé est préfixé par un underscore et le nom de la classe. On peut cependant contourner cela et toujours afficher le contenu de la variable privée en utilisant la notation _Visibiilite__private.

Il est possible que vous ne voyez pas l’intérêt de tout cela si vous n’avez pas beaucoup d’expérience en programmation. Dans ce cas, il est important de retenir et de vous persuader qu’une immense partie du travail d’un développeur est de s’assurer d’avoir un code le plus clair, concis et modulable possible (en plus d’être fonctionnel bien évidemment). Toutes ces notions liées à l’orienté objet permettent de servir ces objectifs.

Et si vous vous posez toujours la question : oui, on pourrait arriver à des résultats similaires en utilisant une approche non orientée objet mais la qualité générale de notre code serait bien plus mauvaise. De plus, Python nous fournit de nombreux outils et notamment des méthodes pour les types prédéfinis qui ne sont accessible qu’en utilisant l’orienté objet et il serait dommage de s’en priver.

Laisser un commentaire