Les différents types de fonctions
Les méthodes sont des fonctions définies à l’intérieur d’une classe, permettant de manipuler les données de l’objet et d’interagir avec d’autres objets. Elles constituent le comportement des objets et facilitent la communication entre eux. En programmation orientée objet, il existe plusieurs types de méthodes : les méthodes d’instance, les méthodes de classe, les propriétés (getter et setter) et les fonctions utilitaires.
Lors de la conception d’une classe, il est important de faire des choix judicieux quant aux types de méthodes à utiliser. C’est-à-dire qu’il est essentiel de comprendre quand utiliser des méthodes d’instance, des méthodes de classe, des propriétés ou des fonctions utilitaires, et de veiller à ce que chaque méthode soit bien adaptée à son rôle. Il est crucial de ne pas confondre les quatre types de méthodes en programmation orientée objet, car cela pourrait entraîner une mauvaise conception et des difficultés de maintenance dans votre code. Chaque type de méthode a un rôle spécifique et doit être utilisé à bon escient.
Faire le bon choix entre les méthodes d’instance, les méthodes de classe, les propriétés et les fonctions utilitaires permet d’assurer un design clair et cohérent dans votre code. Une bonne compréhension de ces concepts est essentielle pour garantir que les responsabilités soient correctement réparties entre les différentes parties du code, facilitant ainsi la lisibilité, la modularité et la réutilisabilité.
En résumé, il est important de toujours garder à l’esprit les caractéristiques et les utilisations appropriées de chaque type de méthode pour éviter toute confusion. Cela permettra de créer un code bien structuré et d’améliorer la qualité globale du projet.
Les méthodes d’instances
Les méthodes d’instance sont des fonctions qui agissent sur les données d’un objet spécifique (instance) de la classe. Elles ont accès à toutes les propriétés et méthodes de l’objet. Par exemple, une méthode d’instance pour une classe Employé
pourrait être calculer_indexation_salaire
, qui agirait sur le salaire d’un employé particulier selon son ancienneté.
class Employe: nombre_employes = 0 def __init__(self, salaire, adresse): self.__salaire = salaire self.__adresse = adresse self.__anciennete = 0 Employe.nombre_employes += 1 def calculer_indexation_salaire(self): self.__anciennete += 1 self.__salaire = self.__salaire + self.__salaire * self.__anciennete/100
class Employe { public: static int nombre_employes; Employe(double salaire, std::string adresse) : _salaire(salaire), _adresse(adresse), _anciennete(0) { nombre_employes++; } void calculer_indexation_salaire() { _anciennete++; _salaire = _salaire + _salaire * _anciennete / 100; } private: double _salaire; std::string _adresse; int _anciennete; }; int Employe::nombre_employes = 0;
public class Employe { public static int NombreEmployes = 0; private double _salaire; private string _adresse; private int _anciennete; public Employe(double salaire, string adresse) { _salaire = salaire; _adresse = adresse; _anciennete = 0; NombreEmployes++; } public void CalculerIndexationSalaire() { _anciennete++; _salaire = _salaire + _salaire * _anciennete / 100.0; } }
Les méthodes statiques
Les méthodes de classe, également appelées méthodes statiques, sont des fonctions qui appartiennent à la classe elle-même plutôt qu’à une instance. Elles sont généralement utilisées pour effectuer des opérations qui ne dépendent pas de propriétés d’un objet particulier, mais liées à la classe dans son ensemble. Par exemple, une méthode de classe pour une classe Employé
pourrait être nombre_total_employés
, qui ne dépend pas de propriétés d’une instance spécifique d’employé, mais plutôt du nombre total d’employés créés à partir de cette classe.
Dans l’exemple suivant, observez la spécificité du choix de déclaration pour la variable “nombre_employes
“, qui est en réalité elle aussi statique. Comme les méthodes statiques, les variables statiques sont liées à la classe et non à une instance spécifique. Ainsi, la valeur de cette variable est commune à toutes les instances de la classe.
class Employe: nombre_employes = 0 def __init__(self, salaire, adresse): self.__salaire = salaire self.__adresse = adresse self.__anciennete = 0 Employe.nombre_employes += 1 @staticmethod def nombre_total_employes(): return Employe.nombre_employes
class Employe { public: static int nombre_employes; Employe(double salaire, std::string adresse) : _salaire(salaire), _adresse(adresse), _anciennete(0) { nombre_employes++; } static int nombre_total_employes() { return nombre_employes; } private: double _salaire; std::string _adresse; int _anciennete; };
public class Employe { public static int NombreEmployes = 0; private double _salaire; private string _adresse; private int _anciennete; public Employe(double salaire, string adresse) { _salaire = salaire; _adresse = adresse; _anciennete = 0; NombreEmployes++; } public static int NombreTotalEmployes() { return NombreEmployes; } }
Les propriétés
Nous l’avons vu précédemment dans le chapitre de l’encapsulation : les propriétés sont des méthodes spéciales, souvent appelées getter et setter, qui permettent d’accéder et de modifier les données privées d’un objet de manière contrôlée. Les getters sont utilisés pour récupérer la valeur d’une propriété, tandis que les setters permettent de définir une nouvelle valeur pour la propriété. L’utilisation de getters et setters est une bonne pratique pour assurer l’encapsulation et protéger les données internes de l’objet.
Les fonctions utilitaires
Les fonctions utilitaires sont des fonctions qui servent à effectuer des opérations générales et qui ne sont pas directement liées à la logique d’un objet ou d’une classe spécifique. Lorsqu’une fonction utilitaire n’est pas propre à la logique d’un objet (ni public, ni privé), elle ne doit pas faire partie de la classe. Un exemple de fonction utilitaire liée à la classe Employé
pourrait être une fonction calculer_distance_entre_deux_adresses
, qui prendrait en entrée les adresses de deux employés et renverrait la distance entre elles. Cette fonction ne dépend pas directement de la logique spécifique d’un employé ou de ses propriétés, mais elle peut être utile pour gérer des opérations courantes liées aux employés.
def calculer_distance_entre_deux_adresses(addr1: str, addr2: str) return abs(len(addr1) - len(addr2)) class Employe: nombre_employes = 0 def __init__(self, salaire: int, adresse: str): self.__salaire = salaire self.__adresse = adresse self.__anciennete = 0 Employe.nombre_employes += 1
int calculer_distance_entre_deux_adresses(const std::string& addr1, const std::string& addr2) { return std::abs(static_cast<int>(addr1.length()) - static_cast<int>(addr2.length())); } class Employe { public: static int nombre_employes; Employe(int salaire, const std::string& adresse) : _salaire(salaire), _adresse(adresse), _anciennete(0) { nombre_employes++; } private: int _salaire; std::string _adresse; int _anciennete; }; int Employe::nombre_employes = 0;
public static class Utils { public static int CalculerDistanceEntreDeuxAdresses(string addr1, string addr2) { return Math.Abs(addr1.Length - addr2.Length); } } public class Employe { public static int NombreEmployes = 0; private int _salaire; private string _adresse; private int _anciennete; public Employe(int salaire, string adresse) { _salaire = salaire; _adresse = adresse; _anciennete = 0; NombreEmployes++; } }