Java >> Tutoriel Java >  >> Java

Héritage en Java

L'héritage est l'un des concepts de base d'un langage orienté objet tel que Java. L'héritage permet à une nouvelle classe de s'étendre à partir d'une classe existante connue sous le nom de classe parent.

Alors, quand utilisons-nous l'héritage? Considérez un scénario où un véhicule décrit un modèle de transport très général, puis vient une voiture, un vélo et un camion. Ces véhicules sont spécialisés, ils ont donc les caractéristiques générales d'un véhicule. Pour comprendre ce concept en termes simples, le véhicule est une classe de base, et la voiture, la bicyclette et le camion sont les classes dérivées.

Syntaxe d'héritage

En Java, lorsque nous voulons hériter d'une classe, nous utilisons le mot clé extend comme indiqué ci-dessous.

public class bicycle extends vehicle

Dans ce code, le véhicule est la superclasse ou la classe de base et le vélo est une sous-classe ou une classe dérivée. Discutons d'un petit morceau de code pour voir comment l'héritage fonctionne vraiment en Java.

/**
 A class that holds a grade for a graded activity.
 */

 public class GradedActivity
 {
 private double score; // Numeric score

 /**
 The setScore method sets the score field.
 @param s The value to store in score.
 */

 public void setScore(double s)
 {
 score = s;
 }

 /**
 The getScore method returns the score.
 @return The value stored in the score field.
 */
public double getScore()
 {
 return score;
 }

 /**
 The getGrade method returns a letter grade
 determined from the score field.
 @return The letter grade.
 */

 public char getGrade()
 {
 char letterGrade;

 if (score >= 90)
 letterGrade = 'A';
 else if (score >= 80)
 letterGrade = 'B';
 else if (score >= 70)
 letterGrade = 'C';
 else if (score >= 60)
 letterGrade = 'D';
 else
 letterGrade = 'F';

 return letterGrade;
 }
 }

/**
 This class determines the grade for a final exam.
 */

 public class FinalExam extends GradedActivity
 {
 private int numQuestions; // Number of questions
 private double pointsEach; // Points for each question
 private int numMissed; // Questions missed

 /**
 The constructor sets the number of questions on the
 exam and the number of questions missed.
 @param questions The number of questions.
 @param missed The number of questions missed.
 */

 public FinalExam(int questions, int missed)
 {
 double numericScore; // To hold a numeric score

 // Set the numQuestions and numMissed fields.
 numQuestions = questions;
 numMissed = missed;

 // Calculate the points for each question and

 // the numeric score for this exam.
 pointsEach = 100.0 / questions;
 numericScore = 100.0 - (missed * pointsEach);

 // Call the inherited setScore method to
 // set the numeric score.
 setScore(numericScore);
 }

 /**
 The getPointsEach method returns the number of
 points each question is worth.
 @return The value in the pointsEach field.
 */

 public double getPointsEach()
 {
 return pointsEach;
 }

 /**
 The getNumMissed method returns the number of
 questions missed.
 @return The value in the numMissed field.
 */

 public int getNumMissed()
 {
 return numMissed;
 }
 }

Notez que le champ de score de la classe GradedActivity ne fait pas partie des variables de la classe FinalExam car le champ de score est privé. Vous remarquerez également que le constructeur de GradedActivity n'est pas répertorié parmi les membres de la classe FinalExam. C'est parce que les constructeurs de superclasses ne sont pas hérités. Après tout, leur but est de construire des objets de la classe de base.

Approfondissons cet exemple d'héritage.

Le constructeur de la classe FinalExam accepte deux arguments :le nombre de questions de test à l'examen et le nombre de questions manquées par l'étudiant. Ces valeurs sont affectées aux champs numQuestions et numMissed de la classe. Le score numérique est également calculé dans le constructeur. Enfin, une fonction est appelée avec le nom de setScore, et elle a été héritée de la classe de base, c'est-à-dire, gradedActivity.

Comment fonctionnent les constructeurs

Comment les constructeurs fonctionnent-ils ensemble lorsqu'une classe hérite d'une autre ? Question intéressante !

Dans une relation d'héritage, le constructeur de la classe de base s'exécute toujours avant le constructeur de la classe dérivée. Dans ce scénario, la classe GradedActivity n'a qu'un seul constructeur, qui est le constructeur par défaut généré automatiquement par Java. Ainsi, lors de la création d'un objet FinalExam, le constructeur par défaut de la classe de base (GradedActivity) est exécuté juste avant le constructeur de la classe dérivée (FinalExam).

Le fonctionnement des constructeurs est démontré par le code ci-dessous

public class SuperClass1
 {
 /**
 Constructor
 */

 public SuperClass1()
 {

  System.out.println("This is the " +
 "superclass constructor.");
 }
 }

 public class SubClass1 extends SuperClass1
 {
 /**
 Constructor
 */

 public SubClass1()
 {
 System.out.println("This is the " +
 "subclass constructor."); }
}

/**
This program demonstrates the order in which
 superclass and subclass constructors are called.
 */

 public class ConstructorDemo1
 {
 public static void main(String[] args)
 {
   //creating base class object
 SubClass1 obj = new SubClass1();
 }
 }
Program Output
This is the superclass constructor.
This is the subclass constructor.

Application du polymorphisme (surcharge et remplacement)

Commençons par le concept de dépassement. Il y a donc écrasement lorsqu'une classe dérivée peut avoir une méthode avec la même signature qu'une méthode de classe de base. En Java, l'annotation @override est utilisée pour remplacer les fonctions de la classe de base, mais ce n'est pas nécessaire. La surcharge se produit lorsqu'une méthode porte le même nom qu'une ou plusieurs autres
méthodes, mais une liste de paramètres différente. Cependant, la surcharge se produit au sein de la fonction de la même classe et le remplacement se produit entre les fonctions de la base et la classe dérivée.

La distinction entre surcharge et remplacement est importante car elle peut affecter l'accessibilité des méthodes de classe de base dans une classe dérivée. Par exemple, lorsqu'une classe dérivée surcharge une méthode de superclasse, les deux méthodes peuvent être appelées l'objet de la classe dérivée. Cependant, lorsqu'une classe de base remplace une méthode de classe dérivée, seule la version de la classe dérivée peut être appelée avec un objet de classe dérivée.

Le concept de polymorphisme est démontré dans le code ci-dessous.

public class SuperClass3
 {
 /**
 This method displays an int.
 @param arg An int.
 */

 public void showValue(int arg)
 {
 System.out.println("SUPERCLASS: " +
 "The int argument was " + arg);
 }

 /**
 This method displays a String.
 @param arg A String.
 */

 public void showValue(String arg)
 {
 System.out.println("SUPERCLASS: " +
 "The String argument was " + arg);
 }
}

public class SubClass3 extends SuperClass3
 {
 /**
 This method overrides one of the superclass methods.
 @param arg An int.
 */

 @Override
 public void showValue(int arg)
 {
 System.out.println("SUBCLASS: " +
 "The int argument was " + arg);
 }

 /**
 This method overloads the superclass methods.
 @param arg A double.
 */

 public void showValue(double arg)
 {
 System.out.println("SUBCLASS: " +
 "The double argument was " + arg);
 }
}

/**
 This program demonstrates the methods in the
 SuperClass3 and SubClass3 classes.
 */

 public class ShowValueDemo
 {
public static void main(String[] args)
{
  
 // Create a SubClass3 object.
 SubClass3 myObject = new SubClass3();
//When an int argument is passed to showValue, the subclass's method is called because it
//overrides the superclass method
 myObject.showValue(10); // Pass an int.
 myObject.showValue(1.2); // Pass a double.
 myObject.showValue("Hello"); // Pass a String.
 }
 }

Héritage à plusieurs niveaux

L'héritage à plusieurs niveaux est comme une chaîne d'héritage dans laquelle une classe hérite d'une deuxième classe, héritant d'une troisième classe. Un bon exemple d'héritage multiniveau est présenté ci-dessous.

 /**
 This class holds a numeric score and determines
 whether the score is passing or failing.
 */

 public class PassFailActivity extends GradedActivity
 {
 private double minPassingScore; // Minimum passing score

 /**
 The constructor sets the minimum passing score.
 @param mps The minimum passing score.
 */

 public PassFailActivity(double mps)
 {
 minPassingScore = mps;
 }

 /**
 The getGrade method returns a letter grade
 determined from the score field. This
 method overrides the superclass method.
 @return The letter grade.
 */

 @Override
 public char getGrade()
 {

 char letterGrade;

 if (super.getScore() >= minPassingScore)
 letterGrade = 'P';
 else
 letterGrade = 'F';

 return letterGrade;
 }
 }
 
/**
 This class determines a passing or failing grade for
 an exam.
 */

 public class PassFailExam extends PassFailActivity
 {
 private int numQuestions; // Number of questions
 private double pointsEach; // Points for each question
 private int numMissed; // Number of questions missed

 /**
 The constructor sets the number of questions, the
 number of questions missed, and the minimum passing
 score.
 @param questions The number of questions.
 @param missed The number of questions missed.
 @param minPassing The minimum passing score.
 */

 public PassFailExam(int questions, int missed,
 double minPassing)
 {
 // Call the superclass constructor.
 super(minPassing);

 // Declare a local variable for the score.
 double numericScore;

 // Set the numQuestions and numMissed fields.
 numQuestions = questions;
 numMissed = missed;

 // Calculate the points for each question and
 // the numeric score for this exam.
 pointsEach = 100.0 / questions;
 numericScore = 100.0 - (missed * pointsEach);

 // Call the superclass's setScore method to
 // set the numeric score.
 setScore(numericScore);
 }

 /**
 The getPointsEach method returns the number of
 points each question is worth.
 @return The value in the pointsEach field.
 */

 public double getPointsEach()
 {
 return pointsEach;
 }

 /**
 The getNumMissed method returns the number of
 questions missed.
 @return The value in the numMissed field.
 */

 public int getNumMissed()
 {
 return numMissed;
 }
 }
 
import java.util.Scanner;

 /**
 This program demonstrates the PassFailExam class.
 */

 public class PassFailExamDemo
 {
 public static void main(String[] args)
 {
 int questions; // Number of questions
 int missed; // Number of questions missed
 double minPassing; // Minimum passing score

 // Create a Scanner object for keyboard input.
 Scanner keyboard = new Scanner(System.in);

 // Get the number of questions on the exam.
 System.out.print("How many questions are " +
 "on the exam? ");
 questions = keyboard.nextInt();

 // Get the number of questions missed.
 System.out.print("How many questions did " +
 "the student miss? ");
 missed = keyboard.nextInt();

 // Get the minimum passing score.
 System.out.print("What is the minimum " +
 "passing score? ");
 minPassing = keyboard.nextDouble();

 // Create a PassFailExam object.
 PassFailExam exam =
 new PassFailExam(questions, missed, minPassing);

 // Display the points for each question.
 System.out.println("Each question counts " +
 exam.getPointsEach() + " points.");

 // Display the exam score.
 System.out.println("The exam score is " +
 exam.getScore());

 // Display the exam grade.
 System.out.println("The exam grade is " +
 exam.getGrade());
 }
 }

Conclusion

L'héritage est un sujet très vaste lors de la discussion des principes orientés objet, et il implique également une fondation pour d'autres principes comme le polymorphisme et l'abstraction. Par conséquent, les exemples de cet article sont élaborés et traitent de l'approche approfondie de l'héritage et du polymorphisme.


Balise Java