Les classes Dart, l’héritage et le polymorphisme

Dans des classes Dart nous avons des variables (propriétés), des constructeurs et des méthodes (fonctions).

Dart est un langage orienté objet, et tous ce que vous manipulez dans un programme Dart est un objet. Un objet représente une instance d’une classe et une classe est un modèle ou une instance d’un autre objet.

classes Dart

En fait, chaque objet possède deux caractéristiques principales :
l’état – certaines données que l’objet va stocker, et le comportement – ​​les actions que l’objet pourrait effectuer.

Nous déffinissons une classe à l’aide du mot-clé class :

class Person{                                          
}

Créer une classe Dart

Nous définissons une classe Person, la première lettre est en majuscule. Le nom de la classe est suivi par deux accolades, entre lesquelles est placé le corps de notre classe, c’est-à-dire ses champs (propriétés ou attributs) et ses méthodes.

Pour stocker des données dans une classe, nous utilisons les champs ou les variables de la classe. Les méthodes (des fonctions) sont utilisées pour déterminer le comportement d’un objet dans une classe. Par exemple, une classe Person qui représente une personne peut avoir la définition suivante :

class Person{
     String nom = "indéfini";      
     int age = 0;                    
     void infos(){
        print("Nom: $nom Age: $age");
    }

En fait, la classe Person possède deux champs, nom, qui représente le nom de la personne et agequi stockera son âge. Puis nous avons une fonction infos(), qui, dans une classe s’appelle méthode.

Cette méthode ne renvoie rien, d’ou l’utilisation du mot void. Cependant, la méthode infos() affiche des informations sur une personne.

Pour faire simple, une classe est un modèle qui stocke les propriétés de l’objet ainsi que les actions qu’ils peut effectuer.

Les variables nom et age sont de types String et int, qui n’acceptent pas les valeurs nulles. Donc, nous devons fournir à ces variables des valeurs initiales.

Cependant, nous pourrions utiliser le type nullable en utilisant le signe ?, ce qui rend les valeurs initiales optionnelles.

class Person{
     String? nom;      
     int? age;                    
     void infos(){
        print("Nom: $nom Age: $age");
    }

Nous avons déjà utilisé l’opérateur ? dans le tutoriel sur les fonctions Dart.

Donc notre classe pourrait ressembler à ceci :

void main() {
  Person marie; // marie est un objet de type Person
}
class Person{
     String nom = "indéfini";      
     int age = 0;                    
     void infos(){
        print("Nom: $nom Age: $age");
    }
}

Rappelez-vous bien de cette syntaxe Person marie, afin que vous compreniez les concepts à venir. L’idée ici est que nous pouvons d’ors et n’avant créer des objets de type Person. C’est la même chose que lorsque vous déclarez une variable avec :
int nombre.

Le constructeur dans les classes Dart

Dans une classe Dart nous pouvons définir des méthodes spéciales, appelées constructeurs. Dart appel le constructeur lors de la création d’un nouvel objet d’une classe. Les constructeurs effectuent l’initialisation de l’objet.

Si Dart ne trouve aucun constructeur dans la classe, il créera automatiquement un constructeur sans paramètres.

La classe Person définie ci-dessus n’a pas de constructeur. Toutefois, il sera créé par défaut, et nous pourrons l’utiliser pour créer un objet Person. Exécutez ce code et admirez la magie des classes :

void main() {

  //instancier un objet marie
  Person marie = Person(); 
  
  // changer les valeurs de nom et age
  marie.nom = "Marie";
  marie.age = 25;
  marie.infos();
   
}
// créer une classe Person
class Person{
     String nom = "indéfini";      
     int age = 0;                    
     void infos(){
        print("Nom: $nom Age: $age");
    }
}

Exécution du code.

Nom: Marie Age: 25

Pour créer un objet Person, nous avons utilisé l’expression Person(). En fait, les anciennes versions de Dart utilisaient également le mot newpour appeler le constructeur.
Person marie = new Person ();. Mais dans les versions récentes de Dart, cet opérateur peut être négligé.

En fait, le constructeur par défaut n’accepte aucun paramètre. Par conséquent, l’exécution de cette expression, allouera un espace en mémoire pour stocker toutes les données de l’objet Person. Et la variable marie va avoir une référence à l’objet créé.

Si le constructeur n’initialise pas les valeurs des variables de l’objet, alors ils auront les valeurs par défaut, c’est-à-dire la valeur null (l’absence réelle d’une valeur).

La création d’un objet de classe ou l’instanciation, permet d’accéder aux variables et méthodes de l’objet Person via la variable marie. Donc, nous avons utilisé l’opérateur point (.) – c’est-à-dire que nous spécifions le nom du champ ou de la méthode avec un point : marie.nom. Par exemple, pour définir les valeurs des champs nous utiliserons :

marie.nom = "Marie";
marie.age = 25;

Créer un constructeur d’une classe Dart

Un constructeur d’une classe Dart permet d’initialiser et de définir les valeurs de notre objet. Le constructeur prend le même nom de la classe et utilise un mot clé this.

class Person{
     String nom = "";      
     int age = 0;  
  
  // le constructeur
  Person(String nom, int age){
    
    this.nom = nom;
    this.age = age;  
  }
  
     void infos(){
        print("Nom: $nom Age: $age");
    }
}

void main() {
  //instancier un objet marie
  Person marie = Person('Marie', 25); 
  
  print(marie.nom);
  print(marie.age);
}
Marie
25

Le mot-clé this est utilisé pour faire référence à l’instance, dans notre cas marie. Ici, nous disons à Dart de remplacer la variable nom par celle de l’objet dans le constructeur. Ce qui va nous permettre de les utiliser en faisant référence à la classe.

Si les arguments et les variables ont des noms différents, inutile de l’utiliser.

Notez que le constructeur prend deux paramètres. Par conséquent, vous devez instancier votre objet en utilisant deux paramètres.
Person marie = Person('Marie', 25).

Cette manière est courante dans la plupart des langages de programmation. Cependant, Dart fournit un moyen plus simple de le faire :

Person(this.nom, this.age);

Remplacez le bloc de code du constructeur par cette ligne de code. En fait, vous pouvez laisser les deux accolades ou utiliser un point virgule.

Les constructeurs nommés

Nous pouvons utiliser des constructeurs nommés pour pouvoir initialiser une classe de différentes manières.
En fait, pour définir plusieurs constructeurs nous écrivons nom_du_constructeur.Nom.
Il peut être utilisé comme une alternative à la  » surcharge de constructeur  » trouvée dans d’autres langages .

class Chien {
  var nom;
  // constructeur simple
  Chien() {
    this.nom = 'inconu';
  }
  // constructeur nommé
  Chien.nom(this.nom);
}

main() {
  var chien = Chien.nom('Tango');
  print(chien.nom); 
}
Tango

Les classes Dart et le type null

Les types de données Dart intégrés n’autorise pas une valeur nulle. Cependant, si nous voulons stocker une valeur nulle dans un objet de la classe , nous pouvons utiliser la classe nullable, en ajoutant l’opérateur ? à la définition de type.

void main() {
  
  Person? marie;
  print(marie);  // null    - marie accepte la valeur null
  
  Person tom;
  // print(tom);  // ! Erreur, tom n'accepte pas null

Exécution du code.

null

Si vous enlever le signe de commentaire de print(tom), vous aurez une erreur, parce que vous n’avez pas affecté une valeur initiale à la variable avant de l’utiliser.

De plus, nous avons un autre problème, on va faire référence à un champ d’un objet à travers une variable qui n’est pas initialisée. Cependant, nous ne pouvons pas accéder aux champs d’un objet inexistant.

marie.age = 25;// Erreur, marie = null

Pour éviter ce problème, nous pouvons utiliser l’opérateur ? pour accéder aux champs.

void main() {
  
  Person? marie; 
  marie?.age = 19 ; 
  marie?.infos(); 
 
}  

L’opérateur ? vérifie la valeur de la variable, si elle n’est pas nulle, alors l’accès à ses champs et méthodes se produit. Si elle est nulle, la référence à la variable sera ignorée. Rien ne s’affiche, mais vous n’aurez pas une erreur.

Les getters et setters

Dans une classe Dart, il existe des méthodes de classe utilisées pour initialiser et récupérer respectivement les valeurs des champs de classe. La méthode setter est utilisée pour la définition d’une variable et la méthode getter pour la récupérer. En fait, elles existent par défaut dans une classe, toutefois nous pouvons les définir si nous le voulons.

Un getter n’a pas de paramètres et renvoie une valeur, et un setter a un paramètre et ne renvoie aucune valeur.

class Person{
     String nom = "";      
     int age = 0;  
  
     void set leNom(String nom){
       this.nom = nom; //this désigne l'instance
     }
  
    String get leNom{
      return nom;
    }
}

void main() {
  
  Person marie = Person(); //instancier un objet marie
  
  marie.nom = 'Marie';
  
  print(marie.leNom);

Exécution du code.

Marie

Notez que nous avons utilisé les mots clés set et get avec la même fonction à savoir leNom. De plus, la fonction getter n’est pas définie avec des parenthèses.

L’idée ici, est que nous avons utilisé une seule fonction (leNom) pour définir (set) et récupérer (get) la valeur envoyée par une instance (marie).

L’héritage des classes Dart

L’héritage est la pierre angulaire de la programmation objet. En utilisant le mot clé extends, vous pouvez permettre à une classe enfant d’hériter les propriétés et les méthodes d’une autre classe parente. De plus, la classe enfant a accès aux propriétés et méthodes de sa propre classe ainsi qu’à la classe de base.

En fait, dans le langage Dart, la classe Objet est la Super classe (parente) de toutes les classes. Par conséquent, chaque classe est dérivée d’au moins une classe ou a au moins une classe parente à l’exception de la classe Object.

L’héritage simple

Une classe hérite uniquement d’une autre classe.

class A{
	afficherA(){
		print("A");
	}
}

class B extends A{
	afficherB(){
		print("B");
	}
}

void main(){
	A a = A();    // instancier un objet a
	B b = B();    // instancier un objet b
	a.afficherA();
        print('');   // sauter une ligne
	b.afficherA(); // b appel une méthode héritée de A
	b.afficherB(); // b appel sa propre méthode
}
A

A
B

La classe B a hérité la méthode afficherA().

L’héritage multi-niveaux

C’est lorsque la classe hérite d’une classe enfant. Une classe C hérite d’une classe B qui elle même hérite d’une classe A.

class A{
	afficherA(){
		print("A");
	}
}

class B extends A{
	afficherB(){
		print("B");
	}
}

class C extends B{
  afficherC(){
    print("C");
  }
}

void main(){
    // instancier des objets a, b et c
    A a = A();
    B b = B();
    C c = C();
  
    a.afficherA();
     
    print('');       // sauter une ligne
    b.afficherA();   // b appel la méthode héritée de la classe A
    b.afficherB();   // b appel sa propre méthode
  
    print('');       // sauter une ligne
    c.afficherA();   // c appel la méthode héritée de la classe A
    c.afficherB();   // c appel la méthode héritée de la classe B
    c.afficherC();   // c appel sa propre méthode
   
}
A

A
B

A
B
C

Donc, la classe C qui hérite de la classe B qui a hérité de la classe A, a accédé aux méthodes des classes A et B.

L’objectif de l’héritage est de pouvoir réutiliser le code d’une autre classe, ce qui nous évitera de réécrire le même code encore et encore.

Afin d’améliorer la structure et la performance du code, le concept de l’héritage est largement utilisé par les développeurs.

Notez que, contrairement à d’autres langages de programmation, une classe Dart ne peut pas hériter directement de plusieurs classes .

Le polymorphisme dans les classes Dart

Le mot polymorphisme signifie « avoir plusieurs formes ». En fait, le polymorphisme est associé avec l’héritage à partir d’une classe parente commune. Nous disons que nous avons un polymorphisme lorsque l’appel d’une méthode entraîne l’exécution d’une opération différente selon le type d’objet appelant la méthode.

Le polymorphisme signifie simplement qu’une même méthode peut avoir différentes applications.

Les sous-classes ou les classes enfants remplacent généralement les méthodes d’instance, les getters et les setters. On peut utiliser @override pour indiquer que nous modifions le comportement d’une méthode.

class Etudiant{
  void langage(){
    print("apprendre la programmation.");
  }
}

class Etudiant1 extends Etudiant{
  // modifier la méthode du parent
  @override
  void langage(){
    print("apprendre Dart.");
    super.langage(); // appeler la méthode du parent
  } 
}

void main(){ 
  Etudiant1 e =  Etudiant1(); // instancier un objet e
  e.langage();
}
apprendre Dart.
apprendre la programmation.

La classe Etudiant1 hérite de la classe Etudiant.
Nous avons modifié la méthode héritée langage.
On a utilisé @override au dessus de la méthode pour dire qu’elle a été modifiée.
Nous utilisons le mot clé super pour appeler une méthode de la classe parente dans la classe enfant.

Les classes Dart, l’héritage et le polymorphisme

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

Retour en haut