Nous utilisions auparavant des classes pour créer de nouveaux types et utilisions l'héritage pour faciliter notre processus de création de classes. Dans cette conférence, je vais plonger dans les types et présenter le concept de polymorphisme.
vérification du type
Toutes les variables et références en Java ne peuvent être utilisées qu'après avoir passé une déclaration de type. Nous avons déjà vu que les données d'objet, les données de classe, les paramètres de méthode, les valeurs de retour de méthode et les variables automatiques à l'intérieur des méthodes doivent tous déclarer leur type. Java est un langage fortement typé, qui vérifie les types. Si nous utilisons le mauvais type, cela provoquera des erreurs.
Le type ne correspond pas, la gentillesse n'est pas valide
Par exemple, dans la classe Test ci-dessous, nous attribuons un objet de classe Cup à une référence de classe Person :
public class Test{ public static void main(String[] args) { Humain aPerson; aPerson = new Cup(); }}class Human{ /** * constructeur */ public Human(int h) { this.height = h; } /** * accesseur */ public int getHeight() { return this.height; } /** * mutateur */ public void growHeight(int h) { this.height = this.height + h } private; int hauteur;}class Cup { public void addWater(int w) { this.water = this.water + w; } public void drinkWater(int w) { this.water = this.water - w } private int water = 0; ;}
javac renverra :
trouvé : Cuprequired : Human aPerson = new Cup(); ^1 erreur
Conversion de type de base
Java peut effectuer une conversion de type sur des variables de types de base. Différents types de base ont des longueurs et des plages de stockage différentes. Si nous convertissons d'un type de haute précision en un type de basse précision, comme la conversion de float en int, nous risquons de perdre des informations. Une telle conversion est appelée conversion restrictive. Dans ce cas, nous devons déclarer explicitement la conversion de type, telle que :
public class Test{ public static void main(String[] args) { int a = (int) 1.23; // conversion restrictive System.out.println(a }}
Si nous passons d'un type de faible précision à un type de haute précision, il n'y a aucun souci de perte d'informations. Une telle transformation est appelée une conversion élargie. Nous n'avons pas besoin d'exiger explicitement une conversion de type, Java peut le faire automatiquement :
public class Test{ public static void main(String[] args) { int a = 3; double b = a; // conversion élargie System.out.println(a }}
Conversion de type de base
upcast et polymorphisme
En Java, les références peuvent également être transtypées, mais il existe des restrictions.
Nous pouvons convertir une référence de classe dérivée en sa référence de classe de base, appelée conversion ascendante ou assouplie. La classe BrokenCup suivante hérite de la classe Cup et remplace les méthodes addWater() et drinkWater() d'origine dans la classe Cup :
public class Test{ public static void main(String[] args) { Cup aCup; BrokenCup aBrokenCup = new BrokenCup(); aCup = aBrokenCup; // upcast aCup.addWater(10); // liaison de méthode }}class Cup { public void addWater(int w) { this.water = this.water + w; } public void drinkWater(int w) { this.water = this.water - w; } private int water = 0;} class BrokenCup extends Cup{ public void addWater(int w) { System.out.println("merde, tasse cassée"); println("om...num..., pas d'eau à l'intérieur"); }}
Résultats de l'exécution du programme :
merde, tasse cassée
Comme vous pouvez le voir ci-dessus, sans aucune instruction explicite, nous attribuons la référence de classe dérivée aBrokenCup à sa référence de classe de base aCup. La conversion de type sera effectuée automatiquement par Java.
Nous avons ensuite appelé la méthode addWater() de aCup (que nous avons déclarée de type Cup). Bien que aCup soit une référence de type Cup, elle appelle en fait la méthode addWater() de BrokenCup ! En d'autres termes, même si nous assouplissons le type de référence à sa classe de base via la conversion ascendante, Java peut toujours identifier correctement le type de l'objet lui-même et appeler la bonne méthode. Java peut identifier le vrai type d'un objet en fonction de la situation actuelle. C'est ce qu'on appelle le polymorphisme. Le polymorphisme est un aspect important de l'orientation objet.
Le polymorphisme est un mécanisme pris en charge par Java et constitue également un concept orienté objet important. Cela soulève une question taxonomique quant à savoir si les objets de sous-classe « sont » réellement des objets de classe parent. Par exemple, un oiseau est aussi un animal ; une voiture doit aussi être un moyen de transport. Java nous indique qu'un objet de classe dérivé peut être utilisé comme objet de classe de base et Java gérera cette situation correctement.
Par exemple, la relation d'héritage suivante :
On peut dire que nous buvons de l’eau dans une tasse. En fait, la signification spécifique de l’action de l’eau potable changera considérablement dans la classe dérivée. Par exemple, boire de l'eau avec une paille et boire de l'eau avec une tasse cassée sont très différents, même si nous parlons tous de « l'eau potable » de manière abstraite. Bien sûr, nous pouvons programmer séparément pour chaque classe dérivée et appeler différentes méthodes drinkWater. Cependant, en tant que programmeurs, nous pouvons programmer une tasse et appeler la méthode drinkWater() de Cup, quel que soit le type de tasse dérivée. Java appellera la méthode correcte correspondante, comme nous pouvons le voir dans le programme ci-dessus.
En regardant un exemple plus significatif, nous ajoutons une méthode drink() à la classe Human. Cette méthode reçoit un objet cup et un entier comme paramètres. Les nombres entiers représentent la quantité d'eau à boire :
public class Test{ public static void main(String[] args) { Invité humain = new HumanCup hisCup = new BrokenCup(); , int w) { aCup.drinkWater(w);
Résultats de l'exécution du programme :
merde, pas d'eau à l'intérieur
Dans la définition de drink() de la classe Human, nous exigeons que le premier paramètre soit une référence de type Cup. Mais dans l'application réelle (classe Test), l'objet de classe dérivé BrokenCup de Cup est utilisé. Cela transfère en fait hisCup vers la classe Cup et le transmet à la méthode drink(). Dans la méthode, nous avons appelé la méthode drinkWater(). Java a découvert que cet objet était en fait un objet BrokenCup, il a donc appelé la méthode correspondante de BrokenCup.
abattu
Nous pouvons downcaster une référence de classe de base en une référence de classe dérivée, mais l'objet pointé par la référence de classe de base est déjà l'objet de classe dérivée à downcast. Par exemple, la hisCup ci-dessus peut être transformée vers le haut en une référence de classe Cup, puis transformée vers le bas en une référence de classe BrokenCup.
Type d'objet
En Java, toutes les classes ont en fait un ancêtre d’héritage commun, qui est la classe Object. La classe Object fournit certaines méthodes, telles que toString(). Nous pouvons remplacer ces méthodes dans notre propre définition de classe.
Objet : ancêtre
Nous pouvons écrire un programme qui exploite des objets Object et transmettre n'importe quel objet au programme via upcast.
J'aborderai la classe Object plus tard.
(L'implémentation du polymorphisme repose sur le support RTTI. J'y reviendrai plus en détail plus tard.)
Résumer
Conversion de type de base
polymorphisme
abattu
Objet