Java >> Java tutorial >  >> Java

Arv i Java

Arv er et af kernebegreberne i et objektorienteret sprog som Java. Nedarvning tillader en ny klasse at udvide fra en eksisterende klasse kendt som overordnet klasse.

Så hvornår bruger vi arv? Overvej et scenarie, hvor et køretøj beskriver en meget generel transportmodel, og derefter kommer en bil, cykel og lastbil. Disse køretøjer er specialiserede, så de har de generelle karakteristika for et køretøj. For at forstå dette koncept i enkle vendinger er køretøjet en basisklasse, og bil, cykel og lastbil er de afledte klasser.

Syntaks for arv

I Java, når vi ønsker at arve en klasse, bruger vi nøgleordet extends som vist nedenfor.

public class bicycle extends vehicle

I denne kode er køretøjet superklassen eller basisklassen, og cyklen er en underklasse eller en afledt klasse. Lad os diskutere et lille stykke kode for at se, hvordan arv virkelig fungerer i 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;
 }
 }

Bemærk, at GradedActivity-klassens scorefelt ikke er blandt variablerne i FinalExam-klassen, fordi scorefeltet er privat. Du vil også bemærke, at GradedActivitys konstruktør ikke er opført blandt medlemmerne af FinalExam-klassen. Dette skyldes, at superklasse-konstruktører ikke nedarves. Deres formål er trods alt at konstruere objekter af basisklassen.

Lad os dykke dybere ned i dette eksempel på arv.

Konstruktøren af ​​FinalExam-klassen accepterer to argumenter:antallet af testspørgsmål på eksamen og antallet af spørgsmål, som den studerende savner. Disse værdier er tildelt numQuestions og numMissed felterne i klassen. Den numeriske score beregnes også i konstruktøren. Til sidst kaldes en funktion med navnet setScore, og den er blevet nedarvet fra basisklassen, dvs. gradedActivity.

Sådan fungerer konstruktører

Hvordan arbejder konstruktørerne sammen, når en klasse arver fra en anden? Interessant spørgsmål!

I et arveforhold udføres basisklassekonstruktøren altid før konstruktøren af ​​den afledte klasse. I dette scenarie har GradedActivity-klassen kun én konstruktør, som er standardkonstruktøren, som Java automatisk genererede. Når et FinalExam-objekt oprettes, udføres standardkonstruktøren for basisklassen(GradedActivity) lige før konstruktøren af ​​den afledte klasse(FinalExam).

Konstruktørernes arbejde demonstreres af koden nedenfor

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.

Anvendelse af polymorfi (overbelastning og tilsidesættelse)

Lad os starte med begrebet tilsidesættelse. Så tilsidesættende er, når en afledt klasse kan have en metode med samme signatur som en basisklassemetode. I Java bruges @override annotation til at tilsidesætte funktioner i basisklassen, men det er ikke nødvendigt. Overbelastning er, når en metode har samme navn som en eller flere andre
metoder, men en anden parameterliste. Overbelastning forekommer dog inden for funktionen af ​​den samme klasse, og tilsidesættelse sker mellem funktionerne i basen og den afledte klasse.

Sondringen mellem overbelastning og tilsidesættelse er vigtig, fordi den kan påvirke tilgængeligheden af ​​basisklassemetoder i en afledt klasse. For eksempel, når en afledt klasse overbelaster en superklassemetode, kan begge metoder kaldes det afledte klasseobjekt. Men når en basisklasse tilsidesætter en afledt klassemetode, kan kun den afledte klasses version kaldes med et afledt klasseobjekt.

Begrebet polymorfi er demonstreret i koden nedenfor.

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.
 }
 }

Arv på flere niveauer

Arv på flere niveauer er som en arvekæde, hvor en klasse arver fra en anden klasse, arver fra en tredje klasse. Et godt eksempel på arv på flere niveauer er vist nedenfor.

 /**
 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());
 }
 }

Konklusion

Arv er et meget stort emne, når man diskuterer objektorienterede principper, og det involverer også et fundament for andre principper som polymorfi og abstraktion. Derfor er eksemplerne i denne artikel uddybende og diskuterer den dybtgående tilgang til arv og polymorfi.


Java tag