Article de reference

Cours (programmation)

En programmation , une classe est une structure d'entité syntaxique utilisée pour créer des objets . Les capacités d'une classe diffèrent selon les langages de programmation , m...

En programmation , une classe est une structure d'entité syntaxique utilisée pour créer des objets . Les capacités d'une classe diffèrent selon les langages de programmation , mais en général, les aspects communs consistent en un état ( variables ) et un comportement ( méthodes ) qui sont chacun associés soit à un objet particulier, soit à tous les objets de cette classe.

L'état d'un objet peut différer d'une instance de la classe à l'autre, tandis que l'état de la classe est partagé par toutes les instances. Les méthodes d'objet permettent d'accéder à l'état de l'objet (via un paramètre implicite ou explicite qui y fait référence), contrairement aux méthodes de classe.

Si le langage prend en charge l'héritage , une classe peut être définie à partir d'une autre classe, en conservant son état et son comportement, ainsi que des états et comportements supplémentaires qui la spécialisent davantage. La classe spécialisée est une sous-classe , et la classe dont elle est issue est sa superclasse .

Dans les langages de programmation purement orientés objet, tels que Java et C# , toutes les classes peuvent faire partie d'un arbre d'héritage tel que la classe racine est Object, ce qui signifie que toutes les instances d'objets sont de Objectou étendent implicitement Object, ce qui est appelé un type supérieur .

Histoire

Ce concept a été introduit principalement dans la programmation orientée objet par le langage Simula dans les années 1960 et est depuis lors utilisé de manière continue dans de nombreux langages de programmation. Sa création s'inspirait d'un concept similaire à celui des blocs utilisés dans le langage de programmation ALGOL 68 , basé sur les a priori .

Attributs

cycle de vie d'un objet

la mémoire correspondant à son état est alors libérée.

La plupart des langages permettent une logique personnalisée lors des événements du cycle de vie via un constructeur et un destructeur .

Taper

Un objet exprime un type de données sous forme d'interface unestructure de données concrète et un ensemble de sous-routines qu'un type est une interface . Différentes classes (concrètes) peuvent produire des objets du même type ( abstrait ) (selon le système de types). Par exemple, le type (interface) Stack peut être implémenté par SmallStack , rapide pour les petites piles mais peu performant à grande échelle, et par ScalableStack , performant à grande échelle mais avec une surcharge importante pour les petites piles.

Structure

Notation UML pour les classes

Une classe contient des champs de données décrits syntaxiquement (ou propriétés , champs , membres de données ou attributs ). Il s'agit généralement de types et de noms de champs qui seront associés à des variables d'état lors de l'exécution du programme ; ces variables d'état appartiennent soit à la classe, soit à des instances spécifiques de celle-ci. Dans la plupart des langages, la structure définie par la classe détermine l'organisation de la mémoire utilisée par ses instances. D'autres implémentations sont possibles : par exemple, en Python , les objets utilisent des conteneurs associatifs clé-valeur.

Certains langages de programmation, comme Eiffel, permettent de spécifier des invariants dès la définition de la classe et de les garantir par le biais du système de types. L'encapsulation de l'état est nécessaire pour pouvoir appliquer les invariants de la classe.

Comportement

ZclassYclassYinterfaceXclassZinterfaceX

Dans les langages qui prennent en charge les spécificateurs d'accès , l'interface d'une classe est considérée comme l'ensemble des membres publics de la classe, y compris les méthodes et les attributs (via des méthodes getter et setter implicites ) ; les membres privés ou les structures de données internes ne sont pas destinés à être utilisés par le code externe et ne font donc pas partie de l'interface.

La méthodologie de programmation orientée objet exige que les opérations de toute interface d'une classe soient indépendantes les unes des autres. Il en résulte une architecture en couches où les clients d'une interface utilisent les méthodes déclarées dans cette interface. Une interface n'impose aucun ordre d'appel de ses opérations. Cette approche présente l'avantage que le code client peut supposer que les opérations d'une interface sont disponibles dès lors qu'il a accès à l'objet.

Exemple d'interface

Les boutons situés en façade de votre téléviseur constituent l'interface entre vous et le câblage électrique dissimulé derrière son boîtier en plastique. Vous appuyez sur le bouton « marche/arrêt » pour allumer ou éteindre le téléviseur. Dans cet exemple, votre téléviseur représente l'instance, chaque méthode est associée à un bouton, et l'ensemble des boutons forme l'interface (d'autres téléviseurs du même modèle que le vôtre possèdent la même interface). De manière générale, une interface est la spécification d'un groupe de méthodes apparentées, sans implémentation associée.

Un téléviseur possède une multitude d' attributs , comme sa taille et sa compatibilité avec la couleur, qui constituent sa structure. Une classe représente la description complète d'un téléviseur, incluant ses attributs (structure) et ses boutons (interface).

Le nombre total de téléviseurs fabriqués pourrait être implémenté par une méthode statique de la classe « téléviseur ». Cette méthode est associée à la classe, mais n'est pas accessible à chaque instance de celle-ci. Une méthode statique permettant de trouver une instance particulière parmi l'ensemble de tous les objets « téléviseur » en est un autre exemple.

Accessibilité des membres

Voici un ensemble courant de spécificateurs d'accès :

  • L'attribut private (ou class-private ) restreint l'accès à la classe elle-même. Seules les méthodes appartenant à la même classe peuvent accéder aux membres privés.
  • L'attribut protected (ou class-protected ) permet à la classe elle-même et à toutes ses sous-classes d'accéder au membre.
  • Public signifie que n'importe quel code peut accéder au membre par son nom.

Bien que de nombreux langages orientés objet prennent en charge les spécificateurs d'accès ci-dessus, leur sémantique peut différer.

La conception orientée objet utilise les spécificateurs d'accès, associés à une conception rigoureuse des implémentations des méthodes publiques, afin de garantir les invariants de classe, c'est-à-dire les contraintes sur l'état des objets. Un usage courant des spécificateurs d'accès consiste à séparer les données internes d'une classe de son interface : la structure interne est rendue privée, tandis que les méthodes d'accès publiques permettent d'inspecter ou de modifier ces données privées.

Les spécificateurs d'accès ne contrôlent pas nécessairement la visibilité , car même les membres privés peuvent être visibles par le code externe du client. Dans certains langages, un membre inaccessible mais visible peut être référencé à l'exécution (par exemple, par un pointeur renvoyé par une fonction membre), mais toute tentative d'utilisation de ce membre par son nom depuis le code client sera bloquée par le vérificateur de types.

Les différents langages de programmation orientés objet imposent l'accessibilité et la visibilité des membres à des degrés divers, et selon leur système de types et leurs règles de compilation, cette imposition peut avoir lieu à la compilation ou à l'exécution . Par exemple, le langage Java interdit la compilation du code client accédant aux données privées d'une classe. En C++ , les méthodes privées sont visibles, mais inaccessibles dans l'interface ; toutefois, elles peuvent être rendues invisibles en déclarant explicitement des classes totalement abstraites représentant les interfaces de la classe.

Certaines langues proposent d'autres systèmes d'accessibilité :

  • Accessibilité par instance vs. par classe : Ruby prend en charge les spécificateurs d’accès `instance-private` et `instance-protected` au lieu de `class-private` et `class-protected`, respectivement. Ils diffèrent en ce qu’ils restreignent l’accès en fonction de l’instance elle-même, plutôt que de la classe de l’instance.
  • Ami : C++ prend en charge un mécanisme permettant à une fonction explicitement déclarée comme fonction amie de la classe d'accéder aux membres désignés comme privés ou protégés.
  • Accès par chemin : Java permet de restreindre l’accès à un membre au sein d’un package Java , selon le chemin logique du fichier. Cependant, il est courant, lors de l’extension d’un framework Java, d’implémenter des classes dans le même package qu’une classe du framework pour accéder à des membres protégés. Le fichier source peut se trouver à un emplacement complètement différent et être déployé dans un fichier .jar distinct , tout en appartenant au même chemin logique du point de vue de la JVM.

Héritage

@interface Voiture : NSObject@property NSString * nom ; @property Moteur * moteur @property NSArray * pneus ;@fin

Cette classe Car possède une instance de NSString (un objet chaîne de caractères ), Engine et NSArray (un objet tableau).

Hiérarchique

Les classes peuvent être dérivées d'une ou plusieurs classes existantes, établissant ainsi une relation hiérarchique entre les classes dérivées ( classes de base , classes parentes ou classes parentes).Les classes parentes (superclasses ) et les classes dérivées (classes enfantsousous-classes) sont liées par unerelation de type « est un/une » . Par exemple, la classe « Button » dérive de la classe « Control ». Ainsi, un Buttonest unControl. Les membres structurels et comportementaux des classes parentes sonthéritéspar les classes enfants. Les classes dérivées peuvent définir des membres structurels (champs de données) et comportementaux (méthodes) supplémentaires, en plus de ceuxhérités, et constituent doncdes spécialisationsde leurs superclasses. De plus, les classes dérivées peuventredéfinirles méthodes héritées si le langage le permet.

Tous les langages ne prennent pas en charge l'héritage multiple. Par exemple, Java permet à une classe d'implémenter plusieurs interfaces, mais elle ne peut hériter que d'une seule classe. Si l'héritage multiple est autorisé, la hiérarchie est un graphe acyclique orienté (DAG) ; sinon, c'est un arbre . Les classes sont représentées par leurs nœuds et les relations d'héritage par leurs liens. Les classes d'un même niveau sont plus susceptibles d'être associées que celles de niveaux différents. Les niveaux de cette hiérarchie sont appelés couches ou niveaux d'abstraction.

Exemple (code Objective-C 2.0 simplifié, issu du SDK iPhone) :

@interface UIResponder : NSObject //... @interface UIView : UIResponder //... @interface UIScrollView : UIView //... @interface UITableView : UIScrollView //...

Dans cet exemple, une UITableView est une UIScrollView est une UIView est une UIResponder est un NSObject.

Modélisation

En analyse orientée objet et en langage de modélisation unifié (UML), une association entre deux classes représente une collaboration entre ces classes ou leurs instances respectives. Les associations sont directionnelles ; par exemple, une association bidirectionnelle entre deux classes indique que les deux classes connaissent leur relation. Les associations peuvent être étiquetées selon leur nom ou leur finalité.

Un rôle d'association est attribué à la fin d'une association et décrit le rôle de la classe correspondante. Par exemple, le rôle « abonné » décrit la manière dont les instances de la classe « Personne » participent à une association « abonnement à » avec la classe « Magazine ». De même, un « Magazine » possède le rôle « magazine abonné » dans la même association. La multiplicité des rôles d'association décrit combien d'instances correspondent à chaque instance de l'autre classe de l'association. Les multiplicités courantes sont « 0..1 », « 1..1 », « 1..* » et « 0..* », où « * » spécifie un nombre quelconque d'instances.

Taxonomie

Il existe de nombreuses catégories de cours, dont certaines se chevauchent.

Abstrait et concret

Une métaclasse est une classe dont les instances sont des classes. Une métaclasse décrit une structure commune à une collection de classes et peut implémenter un patron de conception ou décrire des types de classes particuliers. Les métaclasses sont souvent utilisées pour décrire des frameworks .

Dans certains langages, comme Python , Ruby ou Smalltalk , une classe est aussi un objet ; chaque classe est donc une instance d’une métaclasse unique intégrée au langage. Le système d’objets Common Lisp (CLOS) fournit des protocoles de métaobjets (MOP) pour implémenter ces classes et métaclasses.

Final Une classe finale ne peut pas être héritée. Elle est fondamentalement l'inverse d'une classe abstraite, qui doit être héritée pour être utilisée et ne peut pas être instanciée directement. Une classe finale est implicitement une classe concrète et finalEn Java, C++, PHP ou C#, une classe est déclarée `final` à l'aide du mot-clé `final`. sealedToutefois, il ne faut pas confondre ce concept avec les classes Java qualifiées par le mot-clé ` sealedsubclass`, qui n'autorisent l'héritage que de certaines sous-classes. Dans des langages comme Kotlin , toutes les classes sont `final` par défaut ; pour autoriser l'héritage d'une classe, celle-ci doit être déclarée `final` open.

Par exemple, la classe Java est marquée comme . Stringfinal

Les classes finales peuvent permettre à un compilateur d'effectuer des optimisations qui ne sont pas disponibles pour les classes pouvant être sous-classées.

Scellé

Une « classe scellée » est une classe qui restreint l’héritage à une liste de classes sélectionnées. Il ne faut pas la confondre avec le sealedmot-clé `final` en C#, qui désigne une classe finale. La liste des classes autorisées à hériter de la classe scellée est spécifiée à l’aide d’une permitsclause `if`.

public sealed class Quadrilateral extends Shape implements Renderable , Transformable , Comparable <Quadrilateral> , Measurable permits Parallelogram , Trapezoid , Kite { // ... }

non-sealedest un autre mot-clé utilisé pour déclarer qu'une classe ou une interface qui étend une classe scellée peut être étendue par des classes inconnues.

classe scellée Parallélogramme hérite de Quadrilatère { /* ... */ } classe scellée Rectangle hérite de Parallélogramme { /* ... */ }classe non scellée Square étend Rectangle { /* ... * / }// Comme Square n'est pas scellé, toute classe peut en hériter. class RedSquare extends Square { /* ... */ }

Ouvrir

Une classe ouverte peut être modifiée. En règle générale, un programme exécutable ne peut pas être modifié par les clients. Les développeurs peuvent souvent modifier certaines classes, mais généralement pas les classes standard ou intégrées. En Ruby , toutes les classes sont ouvertes. En Python , les classes peuvent être créées à l'exécution et toutes peuvent être modifiées ultérieurement. Les catégories Objective-C permettent au programmeur d'ajouter des méthodes à une classe existante sans avoir besoin de la recompiler ni même d'accéder à son code source.

Mixin

Certains langages offrent une prise en charge spécifique des mixins . Cependant, dans tout langage prenant en charge l'héritage multiple, un mixin est simplement une classe qui ne représente pas une relation de type « est un type de ». Les mixins servent généralement à ajouter les mêmes méthodes à plusieurs classes ; par exemple, une classe UnicodeConversionMixinpeut fournir une méthode appelée unicodeToAscii()lorsqu'elle est incluse dans des classes FileReaderqui WebPageScraperne partagent pas de parent commun.

Partiel

Dans les langages prenant en charge cette fonctionnalité, une classe partielle est une classe dont la définition peut être divisée en plusieurs morceaux, au sein d'un même fichier source ou répartis sur plusieurs fichiers. Ces morceaux sont fusionnés à la compilation, ce qui donne un résultat identique à celui d'une classe non partielle.

L'introduction des classes partielles vise principalement à faciliter l'implémentation de générateurs de code , tels que les concepteurs visuels . En effet, développer des générateurs de code capables de gérer le code généré lorsqu'il est imbriqué dans du code écrit par le développeur représente un défi, voire un compromis. Grâce aux classes partielles, un générateur de code peut traiter un fichier distinct ou une classe partielle simplifiée au sein d'un fichier, évitant ainsi l'insertion complexe de code généré par une analyse syntaxique approfondie. Ceci améliore l'efficacité du compilateur et élimine le risque de corruption du code du développeur. Dans une implémentation simple des classes partielles, le compilateur effectue une phase de précompilation où il « unifie » toutes les parties d'une classe partielle. La compilation se déroule ensuite normalement

Parmi les autres avantages et effets de la fonctionnalité de classe partielle, on peut citer :

  • Permet de séparer de manière unique l'interface et le code d'implémentation d'une classe.
  • Facilite la navigation dans les classes volumineuses au sein d'un éditeur .
  • Permet la séparation des préoccupations , d'une manière similaire à la programmation orientée aspect, mais sans utiliser d'outils supplémentaires.
  • Permet à plusieurs développeurs de travailler simultanément sur une même classe sans avoir besoin de fusionner ultérieurement le code individuel dans un seul fichier.

Les classes partielles existent depuis longtemps dans Smalltalk sous le nom d' extensions de classes . Avec l'arrivée du framework .NET 2 , Microsoft a introduit les classes partielles, prises en charge à la fois par C# 2.0 et Visual Basic 2005. WinRT prend également en charge les classes partielles.

Ininstanciable

Les classes non instanciables permettent aux programmeurs de regrouper les champs et les méthodes propres à la classe, accessibles à l'exécution sans avoir besoin d'une instance de celle-ci. En effet, l'instanciation est interdite pour ce type de classe.

Par exemple, en C#, une classe marquée comme statique staticne peut pas être instanciée, ne peut avoir que des membres statiques (champs, méthodes, etc.), ne peut pas avoir de constructeurs d'instance et est sealedfinale.

Anonyme

Une classe sans nom ou une classe anonyme n'est pas liée à un nom ou à un identifiant lors de sa définition. Ceci est analogue aux fonctions nommées par rapport aux fonctions sans nom .

interface Greeting { void sayHello (); }// Classe anonyme implémentant Greeting Greeting myGreeting = new Greeting () { @Override public void sayHello () { System . out . println ( "Bonjour de la part d'une classe anonyme !" ); } };myGreeting.sayHello ( ) ;

Avantages

Les avantages de l’organisation des logiciels en classes d’objets se répartissent en trois catégories :

  • Développement rapide
  • Facilité d'entretien
  • Réutilisation du code et des conceptions

Les classes d'objets facilitent le développement rapide car elles réduisent l'écart sémantique entre le code et les utilisateurs. Les analystes système peuvent ainsi communiquer avec les développeurs et les utilisateurs en utilisant un vocabulaire similaire, en parlant de comptes, de clients, de factures, etc. Les classes d'objets facilitent souvent le développement rapide car la plupart des environnements orientés objet intègrent des outils de débogage et de test performants. Les instances de classes peuvent être inspectées à l'exécution pour vérifier que le système fonctionne comme prévu. De plus, plutôt que d'obtenir des dumps de la mémoire mémoire, la plupart des environnements orientés objet offrent des fonctionnalités de débogage interprétées, permettant au développeur d'analyser précisément l'emplacement de l'erreur dans le programme et de voir quelles méthodes ont été appelées, avec quels arguments et avec quels arguments.

Les classes d'objets facilitent la maintenance grâce à l'encapsulation. Lorsqu'un développeur doit modifier le comportement d'un objet, il peut limiter la modification à cet objet et à ses composants. Cela réduit le risque d'effets secondaires indésirables liés aux améliorations apportées lors de la maintenance.

La réutilisation du logiciel est également un avantage majeur de l'utilisation des classes d'objets. Les classes facilitent la réutilisation grâce à l'héritage et aux interfaces. Lorsqu'un nouveau comportement est requis, il est souvent possible de l'obtenir en créant une nouvelle classe qui hérite des comportements et des données par défaut de sa superclasse, puis en adaptant certains aspects du comportement ou des données en conséquence. La réutilisation via les interfaces (ou méthodes) se produit lorsqu'un autre objet souhaite appeler (plutôt que de créer une nouvelle instance de) une classe d'objets. Cette méthode de réutilisation élimine de nombreuses erreurs courantes qui peuvent survenir lors de la réutilisation de code provenant d'un autre programme.

représentation d'exécution

En tant que type de données, une classe est généralement considérée comme une construction de compilation. Un langage ou une bibliothèque peut également prendre en charge des méta-objets prototypes ou fabriques qui représentent des informations d'exécution sur les classes, voire des métadonnées permettant d'accéder à la programmation réflexive et de manipuler les formats de structures de données à l'exécution. De nombreux langages distinguent ce type d' informations d'exécution sur les classes de la classe elle-même, car ces informations ne sont pas nécessaires à l'exécution. Certains langages dynamiques ne font pas de distinction stricte entre les constructions d'exécution et de compilation, et peuvent donc ne pas distinguer les méta-objets des classes.

Par exemple, si Human est un méta-objet représentant la classe Person, alors des instances de la classe Person peuvent être créées en utilisant les fonctionnalités du méta-objet Human .

Programmation basée sur les classes

principe fondamental de la programmation orientée objet. Les critiques soulignent qu'il est possible de créer une classe « sac » stockant une collection d'objets, puis de l'étendre pour créer une nouvelle classe appelée « ensemble » où la duplication des objets est éliminée. Or, une fonction prenant un objet de la classe « sac » peut s'attendre à ce que l'ajout de deux objets augmente la taille du sac de deux. En revanche, si l'on lui passe un objet de la classe « ensemble », l'ajout de deux objets peut ou non augmenter la taille du sac de deux. Le problème survient précisément parce que l'héritage implique le sous-typage même dans les cas où le principe de sous-typage, connu sous le nom de principe de substitution de Liskov , n'est pas vérifié. Barbara Liskov et Jeannette Wing ont formulé ce principe de manière concise dans un article de 1994 :

Exigence de sous-type : Let être une propriété démontrable à propos desde type . Ensuitedevrait être vrai pour lesde typeest un sous-type .

Il convient donc généralement de distinguer le sous-typage et la sous-classification. La plupart des langages orientés objet actuels font cette distinction, mais certaines approches de conception ne la font pas.

Un autre exemple courant est celui d'un objet Personne créé à partir d'une classe enfant ne peut pas devenir un objet de la classe parente, car une classe enfant et une classe parente héritent toutes deux de la classe Personne. Or, la plupart des langages orientés objet n'autorisent pas la modification du type de classe d'un objet à l'exécution. Pour ces langages, cette restriction est essentielle afin de préserver une vue unifiée de la classe pour ses utilisateurs. Ces derniers ne devraient pas avoir à se soucier des éventuelles modifications apportées aux invariants de la classe par l'implémentation d'une méthode. De telles modifications peuvent être effectuées en détruisant l'objet et en en créant un autre. Le polymorphisme permet de préserver les interfaces pertinentes même lors de telles modifications, car les objets sont considérés comme des abstractions « boîte noire » et accessibles via leur identité . Cependant, la valeur des références à l'objet est généralement modifiée, ce qui a des répercussions sur le code client.

Exemples de langues

  • Bloc (programmation) – Groupe délimité d'instructions de code source exécutées séquentiellement
  • Diagramme de classes – Diagramme décrivant la structure statique d'un système logiciel
  • Invariant de classe – Propriété immuable pour tous les objets d'une classe
  • Variable de classe – Variable définie dans une classe dont tous les objets possèdent la même copie
  • Fonction (informatique) – Séquence d'instructions de programme exécutables par d'autres logiciels. Pages affichant de brèves descriptions des cibles de redirection.
  • Variable d'instance – Variable membre d'une classe dont tous les objets possèdent leur propre copie.
  • Métaclasse – Classe décrivant un comportement commun aux classes
  • Objet (informatique) – Instance sémantique dotée d'un état, d'un comportement et d'une identité
  • Syntaxe (langage de programmation) – Forme du code source, sans considération de signification. Pages affichant de brèves descriptions des cibles de redirection.
  • Variable (informatique) – Conteneur nommé pour un type de données particulier. Pages affichant de brèves descriptions des cibles de redirection.

Plus d articles de Worldlex Wiki

Revenez a l index pour explorer davantage de pages sur l histoire, la science, la culture, la geographie et la societe en francais.

Explorer l index