Qu'est-ce que le polymorphisme?
- Réalisez un comportement différent avec des méthodes du même nom
 
- Héritez de la classe Shape des classes Triangle et Rectangle et définissez la méthode getArea avec le même nom.
 
- Comme le type d'objet est différent même pour les variables du même type Shape, la méthode de classe de base / dérivée est appelée en fonction du type d'objet.
 
- ** → Vous pouvez appeler différentes fonctions avec le même nom! ** **
 
- mérite:
 
- Excellente maintenabilité
 
- Le remplacement de fonction n'est qu'un remplacement d'instance
 
- facile à comprendre
 
Shape.java
public class Shape {
  protected double width;
  protected double height;
  public Shape(double width, double height) {
    this.width = width;
    this.height = height;
  }
//Récupère l'aire de la figure (remplacement dans la classe dérivée)
  public  double getArea() {
    return 0d;
  }
  //public abstract double getArea();
}
Triangle.java
public class Triangle extends Shape {
  public Triangle(double width, double height) {
    super(width, height);
  }
//Obtenez l'aire d'un triangle
  @Override
  public double getArea() {
    return this.width * this.height / 2;
  }
}
Rectangle.java
public class Rectangle extends Shape {
  public Rectangle(double width, double height) {
    super(width, height);
  }
//Obtenez la superficie de la place
  @Override
  public double getArea() {
    return this.width * this.height;
  }
}
public class PolymorphismBasic {
  public static void main(String[] args) {
    //Attribuer un objet de type Triangle (upcast)
    Shape tri = new Triangle(10, 50);
    //Attribuer un objet de type Rectangle (upcast)
    Shape rec = new Rectangle(10, 50);
    System.out.println(tri.getArea()); //250.0
    System.out.println(rec.getArea()); //500.0
  }
}
Méthode abstraite
- Dans l'exemple ci-dessus, la classe de base Shape s'attend à remplacer la méthode getArea, mais ce n'est pas obligatoire.
 
- ** Méthode abstraite **: Aucun contenu (fonction) en soi ** Méthode vide **
 
- ** Classe abstraite **: Classe contenant des méthodes abstraites
 
- Les classes qui héritent des classes abstraites sont obligées de remplacer toutes les méthodes abstraites **
 
- Les méthodes abstraites peuvent garantir que certaines méthodes sont remplacées dans les classes dérivées **
 
Comment utiliser
- ** Ajouter le modificateur 
abstract à la définition de méthode abstraite ** 
- La classe de base ne peut pas avoir de contenu de bloc, elle se termine uniquement par 
; 
- ** Ajoutez le modificateur 
abstract au bloc de classe pour les classes contenant des méthodes abstraites ** 
Shape.java
public abstract class Shape {
  protected double width;
  protected double height;
  public Shape(double width, double height) {
    this.width = width;
    this.height = height;
  }
 //Vous ne pouvez pas avoir de contenu dans la classe de base!
  public abstract double getArea();
}
interface
- Java n'autorise pas l'héritage multiple, donc une seule classe peut être héritée à la fois
 
- Les méthodes inutiles doivent être remplacées pour le moment
 
- → ** Utiliser l'interface **
 
- Une classe dans laquelle toutes les méthodes subordonnées sont des méthodes abstraites
 
- L'héritage multiple est possible
 
- Chaque méthode est divisée en différentes interfaces dans un bloc sémantique
 
- Seules les méthodes nécessaires peuvent être sélectionnées du côté de la classe dérivée
 
Définition d'interface
- Instruction 
interface 
- ** public **: accessible depuis toutes les classes
 
- ** abstract **: Classe abstraite
 
- ** strictfp **: la virgule flottante est calculée de manière indépendante de l'environnement
 
- Puisqu'il est clair qu'une méthode abstraite est incluse en dessous, il en est de même même si le résumé n'est pas ajouté (généralement omis)
 
- Le nom de l'interface est la notation Pascal
 
public interface Shape {
  double getArea();
}
Membre définissable
- Méthode abstraite
 
- méthode par défaut
 
- Méthode de classe
 
- Champ constant
 
- Classe / interface statique imbriquée
 
Implémentation de l'interface
- ** Définissez une classe en héritant de l'interface prédéfinie **
 
- La classe qui implémente l'interface est appelée ** classe d'implémentation **
 
implémente le nom de l'interface 
- Lors de la mise en œuvre de plusieurs interfaces, 
implémente Shape, Hoge, Bar 
- Combiné avec l'héritage 
étend MyParent implémente Shape 
//Classe d'implémentation d'interface de forme
public class Rectangle implements Shape {
  private double width;
  private double height;
  public Rectangle(double width, double height) {
    this.width = width;
    this.height = height;
  }
  @Override
  public double getArea() {
    return this.width * this.height;
  }
}
Membre de l'interface
- Méthode abstraite, champ constant, méthode par défaut, méthode statique (Java8 ou version ultérieure)
 
Champ constant
- ** Le champ d'interface ne peut pas être défini car l'interface ne peut pas être instanciée **
 
- Les champs sont inconditionnellement 
public static final 
- Puisqu'il est redondant, écrivez comme suit
 
interface MyApp{
    String TITLE = "Chevaliers des oiseaux immortels";
    double NUMBER = 5;
}
champ statique (Java 8 ou version ultérieure)
- Lorsque vous souhaitez résumer certaines fonctions liées à l'interface existante
 
méthode par défaut (Java 8 ou version ultérieure)
- Implémentation adoptée par défaut lorsqu'elle n'est pas explicitement implémentée du côté de la classe d'implémentation
 
public interface Loggable {
  default void log(String msg) {
    System.out.println("Log: " + msg);
  }
}
//Ne remplacez pas la méthode de journalisation
public class LoggableImpl implements Loggable {
}
InterfaceDefault.java
public class InterfaceDefault {
  public static void main(String[] args) {
    var l = new LoggableImpl();
    //La méthode par défaut de la classe Loggable est appelée
    l.log("Harry Potter"); //Log:Harry Potter
  }
}
- Vous pouvez également appeler explicitement la méthode par défaut de la classe d'implémentation avec super
 
//Ne remplacez pas la méthode de journalisation
public class LoggableImpl implements Loggable {
  @Override
  public void log(String msg) {
    Loggable.super.log(msg);
    System.out.println("LogImpl: " + msg);
  }
}
InterfaceDefault.java
public class InterfaceDefault {
  public static void main(String[] args) {
    var l = new LoggableImpl();
    l.log("Harry Potter"); 
    //Log:Harry Potter
    //LogImpl:Harry Potter
  }
}
Remarque sur l'héritage multiple
Méthode abstraite en double
- ** Erreur de compilation lorsque le nom de la méthode et le type d'argument sont identiques mais que seule la valeur de retour est différente **
 
- La valeur de retour côté implémentation doit être le type dérivé le plus bas
 
public interface IHoge {
  void foo();
  //CharSequence foo(); //OK
}
public interface IHoge2 {
  String foo();
}
public class HogeImpl implements IHoge, IHoge2 {
    @Override
    public String foo() { } //Le type de retour est IHoge.foo()Non compatible avec
}
Dupliquer les champs constants
- ** Erreur de référence ** même si les types de données sont différents ou les types / valeurs sont les mêmes **
 
public interface Hoge {
  int DATA = 0;
}
public interface Hoge2 {
  String DATA = "This is an apple.";
}
public class HogeImpl implements Hoge, Hoge2 {
  public void foo() {
    System.out.println(DATA); //Erreur
  }
}
Dupliquer la méthode par défaut
- ** Puisqu'il a une implémentation, une erreur se produira même si le nom de la méthode, l'argument et la valeur de retour correspondent tous **
 
- Il est possible de faire explicitement référence à la méthode defalt dans la classe d'implémentation avec 
super 
- S'il y a une différence dans la hiérarchie, vous pouvez utiliser la méthode par défaut avec le même nom.
 
- La priorité est donnée aux classes avec une relation d'implémentation plus étroite (relation d'implémentation directe)
 
public interface DHoge {
  default void log(String msg) {
    System.out.println("DHoge: " + msg);
  }
}
public interface DHoge2 {
  default void log(String msg) {
    System.out.println("DHoge2: " + msg);
  }
}
public class HogeImpl implements DHoge, DHoge2 {
  @Override
  public void log(String msg) {
    DHoge.super.log(msg); //Erreur (le journal de méthode par défaut en double avec String est DHoge2,(Hérité de DHoge)
    //IHoge.super.log(msg); //La référence explicite est OK
  }
}
Lequel utiliser, interface ou classe abstraite?
- Priorité d'interface
 
- La classe est ** hiérarchie d'arbre ** avec la classe Object en tant que racine
 
- Interface: ** Indépendant de l'arborescence de classes **
 
- Classe abstraite: ** Partie de l'arborescence des classes **
 
- La hiérarchie des types n'est pas une expression de toute réalité
 
- S'il s'agit d'une interface
 
- Parce qu'il est indépendant de la hiérarchie des types **, il est possible d'interrompre une fonction spécifique **
 
- ** Une nouvelle interface peut être implémentée quelle que soit la classe de base **
 
- ** Héritage multiple possible **
 
- Pour les cours de résumé
 
- ** Identifier les classes connexes et les placer dans tous les postes de classe supérieure ** Obligatoire
 
- L'héritage ne peut pas être refusé même s'il y a des fonctions inutiles au milieu **
 
- Lors de l'adoption, vous devriez regarder l'implémentation plutôt que la méthode de la classe (comportement de la classe)
 
- Traitement commun dans les classes dérivées
 
- Squelette du processus de mise en œuvre
 
- ex: La classe Writer dans le package java.io fournit le framework 
XWriter dans les classes de base de BufferWriter, OutputStreamWriter, PrintWriter.