1. Transtypage

Les variables qui stockent des types de référence (classes) peuvent également être converties en différents types. Mais cela ne fonctionne que dans une seule hiérarchie de types. Prenons un exemple simple. Supposons que nous ayons la hiérarchie de classes suivante, dans laquelle les classes inférieures héritent des classes supérieures.

Transtypage

Le transtypage des types de référence ainsi que des types primitifs est également classé comme élargissement et rétrécissement.

Nous voyons que la classe Cat hérite de la classe Pet, et la classe Pet, à son tour, hérite de la classe Animal.

Si nous écrivons un code comme celui-ci :

Animal kitten = new Cat();

Il s'agit d'une conversion de type élargissement . On l'appelle aussi cast implicite. Nous avons élargi la référence du chat pour qu'elle fasse désormais référence à un objet Cat . Avec une conversion de type comme celle-ci, nous ne pourrons pas utiliser la référence chaton pour appeler des méthodes qui sont présentes dans la classe Cat mais absentes dans la classe Animal .

Une conversion restrictive (ou conversion explicite) se produit dans la direction opposée :

Cat cat = (Cat) kitten;

Nous avons explicitement indiqué que nous voulions convertir la référence stockée dans la variable chaton (dont le type est Animal ) en type Cat .



2. Vérifier le type d'un objet

Mais vous devez être très prudent ici. Si tu fais ça:

Animal beast = new Cat();
Wolf grayWolf = (Wolf) beast;

Le compilateur autorisera ce code, mais il y aura une erreur lors de l'exécution du programme ! La JVM lèvera une exception :

Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to a Wolf

Les références à un objet Cat ne peuvent être stockées que dans des variables dont le type est un ancêtre de la classe Cat : Pet, Animal ou Object.

Pourquoi donc?

Le point pertinent ici est qu'une référence d'objet est utilisée pour faire référence aux méthodes et aux variables de cet objet . Et il n'y aura aucun problème si nous utilisons une variable Animal pour stocker une référence à un objet Cat : le type Cat a toujours une variable et des méthodes de type Animal — il en a hérité !

Mais si la JVM nous a permis de stocker une référence à un objet Cat dans une variable Wolf, alors nous pourrions avoir une situation où nous pourrions essayer d'utiliser la variable grayWolf pour appeler une méthode qui n'existe pas dans l'objet Cat stocké dans cette variable . C'est pourquoi cet arrangement n'est pas autorisé.

Java a un opérateur spécial instanceofqui vous permet de vérifier si un objet est d'un certain type et peut donc être stocké dans une variable d'un certain type. Ça a l'air assez simple :

variable instanceof Type

Exemple:

Animal beast = new Cat();
if (beast instanceof Wolf)
{
   Wolf grayWolf = (Wolf) beast;
}

Ce code ne provoquera pas d'erreurs, même lors de l'exécution.

Voici quelques exemples supplémentaires qui illustrent la situation :

Conversion de type d'élargissement Description
Cow cow = new Whale();

Il s'agit d'une conversion élargie classique — aucun opérateur de conversion de type n'est requis. Désormais, seules les méthodes définies dans la Cowclasse peuvent être appelées sur l' Whaleobjet.

Sur la cowvariable , le compilateur ne vous laissera appeler que les méthodes que son type (la Cowclasse) a.

Conversion de type de rétrécissement
Cow cow = new Whale();
if (cow instanceof Whale)
{
   Whale whale = (Whale) cow;
}
Conversion de restriction classique : vous devez ajouter une vérification de type et un opérateur de conversion.
La Cow cowvariable stocke une référence à un Whaleobjet.
Nous vérifions que c'est le cas , puis effectuons une conversion de type (rétrécissement). Ou comme on l'appelle aussi :
un casting de type
.

Cow cow = new Cow();
Whale whale = (Whale) cow; // Exception
Vous pouvez restreindre un type de référence sans vérifier le type de l'objet.
Si la cowvariable fait référence à un objet qui n'est pas un Whale, alors un InvalidClassCastExceptionsera généré.


3. Appel de la méthode originale : le supermot clé

Lors de la redéfinition de la méthode d'une classe parente, parfois plutôt que de la remplacer par la nôtre, nous souhaitons simplement la compléter légèrement.

Ce serait cool si nous pouvions la méthode de la classe parente dans notre méthode, puis exécuter une partie de notre propre code. Ou peut-être d'abord exécuter notre propre code, puis appeler la méthode de la classe parent.

Et Java nous permet de faire exactement cela. Pour appeler une méthode de la classe parent, procédez comme suit :

super.method(arguments);

Exemples:

class PeaceTime
{
   public double getPi()
   {
      return 3.14;
   }
}

class WarTime extends PeaceTime
{
   public double getPi()
   {
      return super.getPi()*2;  // 3.14*2
   }
}

En temps de guerre, la valeur de Pipeut être supérieure à 6 ! Bien sûr, nous plaisantons, mais cet exemple montre comment tout cela peut fonctionner.

Voici quelques exemples supplémentaires pour clarifier un peu les choses :

Code Description
class Cow
{
   public void printAll()
   {
      printColor();
      printName();
   }

   public void printColor()
   {
      System.out.println("I'm a white whale");
   }

   public void printName()
   {
      System.out.println("I'm a cow");
   }
}

class Whale extends Cow
{
   public void printName()
   {
      System.out.print("This is incorrect: ");
      super.printName();
      System.out.println("I'm a whale");
   }
}
Cowet Whalecours
public static void main(String[] args)
{
   Whale whale = new Whale();
   whale.printAll();
}
La sortie d'écran sera :
I'm a white whale
This is incorrect: I'm a cow
I'm a whale

C'est quelque chose de difficile. Honnêtement, c'est l'une des choses les plus difficiles en POO . Cela dit, vous devez le connaître et le comprendre.