JavaRush /Blog Java /Random-FR /Classes abstraites en Java avec exemples concrets

Classes abstraites en Java avec exemples concrets

Publié dans le groupe Random-FR
Bonjour! Dans les conférences précédentes, nous nous sommes familiarisés avec les interfaces et avons compris à quoi elles servent. Le sujet d’aujourd’hui aura quelque chose en commun avec le précédent. Parlons des classes abstraites en Java. Classes abstraites en Java avec exemples concrets - 1

Pourquoi les cours sont-ils appelés « abstraits »

Vous vous souvenez probablement de ce qu'est « l'abstraction » - nous en avons déjà parlé :) Si vous avez soudainement oublié, ce n'est pas grave, rappelons-nous : c'est le principe de la POO , selon lequel lors de la conception de classes et de la création d'objets, il faut mettre en évidence uniquement les propriétés principales d’une entité et ignorer les propriétés secondaires. Par exemple, si nous concevons une classe SchoolTeacher- un professeur d'école - il est peu probable que nous ayons besoin de la caractéristique « taille ». En effet : pour un enseignant cette caractéristique n'est pas importante. Mais si nous créons une classe dans le programme BasketballPlayer- un basketteur - la taille deviendra l'une des principales caractéristiques. Ainsi, une classe abstraite est le « blanc » le plus abstrait et le plus approximatif pour un groupe de classes futures. Cette préparation ne peut pas être utilisée sous sa forme finie - elle est trop « crue ». Mais il décrit un certain état général et un certain comportement que les classes futures – héritières de la classe abstraite – auront.

Exemples de classes abstraites Java

Regardons un exemple simple avec des voitures :
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
Voici à quoi ressemble la classe abstraite la plus simple. Comme vous pouvez le constater, rien de spécial :) Pourquoi pourrions-nous en avoir besoin ? Tout d’abord, il décrit de la manière la plus abstraite possible l’entité dont nous avons besoin : une voiture. Le mot abstrait est ici pour une raison. Il n’existe pas de « justes machines » dans le monde. Il y a des camions, des voitures de course, des berlines, des coupés, des SUV. Notre classe abstraite est simplement un « plan » à partir duquel nous créerons plus tard des classes de voitures.
public class Sedan extends Car {

   @Override
   public void gas() {
       System.out.println("The sedan accelerates!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan slows down!");
   }

}
Cela ressemble beaucoup à ce dont nous avons parlé dans les conférences sur l'héritage. Seulement là, nous avions une classe Caret ses méthodes qui n'étaient pas abstraites. Mais cette solution présente un certain nombre d'inconvénients, qui sont corrigés dans les classes abstraites. Tout d’abord, une instance d’une classe abstraite ne peut pas être créée :
public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Cette « astuce » a été implémentée spécifiquement par les créateurs de Java. Encore une fois, rappelez-vous : une classe abstraite n’est qu’un modèle pour les futures classes « normales » . Vous n'avez pas besoin de copies du dessin, n'est-ce pas ? Il n'est donc pas nécessaire de créer des instances d'une classe abstraite :) Et si la classe Carn'était pas abstraite, on pourrait facilement créer ses objets :
public class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       // some logic
   }

   public  void brake() {
       // some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Everything is OK, the machine has been created
   }
}
Maintenant, nous avons une sorte de voiture incompréhensible dans notre programme - pas un camion, pas une voiture de course, pas une berline, mais quelque chose en général. Ce même « juste une machine » qui n’existe pas dans la nature. Le même exemple peut être donné avec les animaux. Imaginez si des objets apparaissaient dans votre programme Animal- « juste un animal ». De quel type il s’agit, à quelle famille il appartient, quelles caractéristiques il possède ne sont pas clairs. Ce serait étrange de le voir au programme. Il n’y a pas de « simples animaux » dans la nature. Uniquement les chiens, chats, renards, taupes et autres. Les classes abstraites nous libèrent des « simples objets ». Ils nous donnent un état et un comportement de base. Par exemple, toutes les voitures doivent avoir un modèle , une couleur et une vitesse maximale , et elles doivent également pouvoir faire le plein d'essence et freiner . C'est tout. Il s'agit d'un schéma abstrait général, puis vous concevez vous-même les cours dont vous avez besoin. Remarque : deux méthodes d'une classe abstraite sont également désignées comme abstract , et elles ne sont pas du tout implémentées. La raison est la même : les classes abstraites ne créent pas de « comportement par défaut » pour de « simples machines ». Ils disent simplement qu’ils devraient être capables de fabriquer toutes les voitures. Toutefois, si vous avez toujours besoin du comportement par défaut, vous pouvez implémenter des méthodes dans une classe abstraite. Java n'interdit pas cela :
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Let's go!");
   }

   public abstract void brake();

   //getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan slows down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
Résultat de la console :  « Accélérez ! » Comme vous pouvez le voir, nous avons implémenté une méthode dans la classe abstraite, mais n'avons pas implémenté la seconde. En conséquence, le comportement de notre classe Sedana été divisé en deux parties : si vous appelez une méthode dessus gas(), elle sera « extraite » de la classe abstraite parent Caret brake()nous avons redéfini la méthode dans la classe Sedan. Cela s'est avéré très pratique et flexible. Mais maintenant notre classe n'est plus si abstraite ? Après tout, en fait, la moitié de ses méthodes sont mises en œuvre. En fait – et c'est une caractéristique très importante – une classe est abstraite si au moins une de ses méthodes est abstraite . Au moins une méthode sur deux, au moins une méthode sur mille - peu importe. Nous pouvons même implémenter toutes les méthodes et n’en laisser aucune abstraite. Il y aura une classe abstraite sans méthodes abstraites. En principe, cela est possible, et le compilateur ne produira pas d'erreurs, mais il vaut mieux ne pas le faire : le mot abstrait perdra son sens, et vos collègues programmeurs seront très surpris de voir cela :/ De plus, si une méthode est marquée du mot abstract, chaque classe descendante doit implémenter ou être déclarée abstract. Sinon, le compilateur générera une erreur . Bien entendu, chaque classe ne peut hériter que d’une seule classe abstraite. Il n’y a donc aucune différence entre les classes abstraites et régulières en termes d’héritage. Peu importe que nous héritions d’une classe abstraite ou d’une classe normale, il ne peut y avoir qu’une seule classe parent.

Pourquoi n’y a-t-il pas d’héritage de classes multiples en Java ?

Nous avons déjà dit qu’il n’y avait pas d’héritage multiple en Java, mais nous n’avons pas vraiment compris pourquoi. Essayons ceci maintenant. Le fait est que si Java avait plusieurs héritages, les classes enfants ne seraient pas en mesure de décider quel comportement choisir. Disons que nous avons deux classes - Tosteret NuclearBomb:
public class Toster {


 public void on() {

       System.out.println("The toaster is on, the toast is getting ready!");
   }

   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Взрыв!");
   }
}
Comme vous pouvez le constater, les deux ont une méthode on(). Dans le cas d’un grille-pain, il commence à cuire des toasts, et dans le cas d’une bombe nucléaire, il provoque une explosion. Oh :/ Imaginez maintenant que vous ayez décidé (je ne sais pas pourquoi tout d'un coup !) de créer quelque chose entre les deux. Et voilà votre classe - MysteriousDevice! Ce code, bien sûr, ne fonctionne pas, et nous le présentons simplement comme un exemple de « comment cela pourrait être » :
public class MysteriousDevice extends Toster, NuclearBomb {

   public static void main(String[] args) {

       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // And what should happen here? Will we get a toast, or a nuclear apocalypse?
   }
}
Voyons ce que nous avons. Le mystérieux appareil provient à la fois du grille-pain et de la bombe nucléaire. Les deux ont une méthode on()et, par conséquent, il n'est pas clair quelle méthode on()doit se déclencher sur l'objet MysteriousDevicesi nous l'appelons. L'objet ne pourra pas comprendre cela. Et bien, cerise sur le gâteau : la bombe nucléaire n'a pas de méthode off(), donc si nous nous trompons, il n'y aura aucun moyen d'éteindre l'appareil. Classes abstraites en Java avec exemples concrets - 2 C'est précisément à cause de cette confusion, lorsqu'un objet ne sait pas quel comportement il doit choisir, que les créateurs de Java ont abandonné l'héritage multiple. Cependant, rappelez-vous que les classes Java implémentent de nombreuses interfaces. D’ailleurs, vous avez déjà rencontré au moins un cours abstrait dans vos études ! Mais peut-être que je ne l'ai pas remarqué :)
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar>
C'est votre ancienne classe d'amis Calendar. Elle est abstraite et a plusieurs héritiers. L'un d'eux est GregorianCalendar. Vous l'avez déjà utilisé dans des cours sur les dates :) Tout semble clair, il ne reste qu'un point : quelle est la différence fondamentale entre les classes abstraites et les interfaces ? Pourquoi ont-ils ajouté les deux à Java, et ne se sont-ils pas limités à un seul ? Cela pourrait bien suffire. Nous en parlerons lors de la prochaine conférence ! À bientôt:)
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION