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
.