Hei! La oss snakke om abstrakte klasser i Java.Konkrete eksempler på abstrakte klasser i Java - 1

Hvorfor kalles klasser "abstrakte"?

Du husker sikkert hva abstraksjon er - vi diskuterte det tidligere :) Hvis du har glemt det, ingen bekymringer. Husk at det er et OOP-prinsipp som sier at når du designer klasser og oppretter objekter, skal du kun representere enhetens hovedegenskaper og forkaste sekundære. For eksempel, hvis vi designer en SchoolTeacherklasse, vil høyde sannsynligvis ikke være en nødvendig egenskap for en lærer. Denne egenskapen er faktisk ikke viktig for en lærer. Men hvis vi lager en BasketballPlayerklasse, vil høyde være en av de viktigste egenskapene. Vel, en abstrakt klasseer det mest abstrakte, "grove arbeidsstykket" for en gruppe fremtidige klasser. Arbeidsstykket kan ikke brukes direkte - det er for "grovt". Men den definerer en viss karakteristisk tilstand og atferd som fremtidige klasser - etterkommerne av den abstrakte klassen - vil ha.

Eksempler på abstrakte klasser i Java

Tenk på et enkelt eksempel med biler:

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;
   }
}
Slik ser den enkleste abstrakte klassen ut. Som du kan se, ikke noe spesielt :) Hvorfor kan vi trenge dette? For det første gir den den mest abstrakte beskrivelsen av enheten vi trenger - en bil. Det abstrakte nøkkelordet betyr noe her. I den virkelige verden er det ikke noe som heter "bare en bil". Det er lastebiler, racerbiler, sedaner, coupéer og SUV-er. Vår abstrakte klasse er rett og slett en "blåkopi" som vi senere skal bruke til å lage spesifikke bilklasser.

public class Sedan extends Car {
  
   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }
  
}
På mange måter ligner dette på det vi snakket om i timene om arv. Bare i det tilfellet hadde vi en Carklasse hvis metoder ikke var abstrakte. Men en slik løsning har flere ulemper som er fikset i abstrakte klasser. Først og fremst kan en forekomst av en abstrakt klasse ikke opprettes:

public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Javas skaper har laget denne "funksjonen" med vilje. Igjen, husk: en abstrakt klasse er bare en blåkopi for fremtidige "vanlige" klasser . Du trenger ikke kopier av en blåkopi, ikke sant? På samme måte er det ikke nødvendig å lage forekomster av en abstrakt klasse :) Og hvis klassen Carikke var abstrakt, kan vi enkelt lage forekomster av den:

public class Car {

   private String model;
   private String color;
   private int maxSpeed;
  
   public void go() {
       // ...some logic
   }

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


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // This is okay. The car is created.
   }
}
For tiden har programmet vårt en slags uforståelig bil. Det er ikke en lastebil, ikke en racerbil, og ikke en sedan, men det er ikke helt klart hva det er. Det er «bare en bil» som ikke eksisterer i virkeligheten. Det samme eksempelet kan gis med dyr. Tenk deg om programmet ditt hadde Animalobjekter (" bare dyr "). Det er ikke klart hva slags det er, hvilken familie det tilhører, eller hvilke egenskaper det har. Det ville vært rart å se en i et program. Det finnes ikke «bare dyr» i naturen. Bare hunder, katter, rever, føflekker osv. Abstrakte klasser redder oss fra " bare gjenstander ". De gir oss grunnlinjetilstand og atferd. For eksempel må alle biler ha modell , farge og toppfart, og de må også kunne bruke gassen og bremse . Det er det. Det er en generell abstrakt blåkopi som du vil bruke senere for å designe klassene du trenger. Merk: de to metodene i abstraktklassen er også abstrakte , noe som betyr at de ikke har noen implementering i det hele tatt. Årsaken er den samme: abstrakte klasser skaper ikke "standardatferd" for "bare biler". De indikerer bare hva hver bil må kunne. Når det er sagt, hvis du trenger standard oppførsel, kan du implementere metoder i en abstrakt klasse. Java forbyr ikke dette:

public abstract class Car {

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

   public void gas() {
       System.out.println("Accelerating!");
   }

   public abstract void brake();
  
   // Getters and setters
}


public class Sedan extends Car {

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

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
Konsollutgang:
Accelerating!
Som du kan se, implementerte vi en metode i abstraktklassen, men ikke den andre. Som et resultat er atferden til Sedanklassen vår delt i to deler: hvis vi kaller gas()metoden dens, blir atferden "trukket opp" fra den abstrakte Caroverordnede klassen, og vi implementerer brake()metoden i Sedanklassen. Det er super praktisk og fleksibelt. Men klassen vår er ikke så abstrakt nå, er det vel ? Tross alt implementerte den faktisk halvparten av metodene. Faktum er - og dette er en veldig viktig funksjon - en klasse er abstrakt hvis til og med en av metodene er abstrakt. En metode av to, eller en av tusen — det spiller ingen rolle. Vi kunne til og med implementere alle metodene, uten å etterlate noen abstrakt. Resultatet ville være en abstrakt klasse uten noen abstrakte metoder. Dette er i prinsippet mulig - kompilatoren vil ikke generere noen feil - men det er bedre å ikke gjøre dette, siden det fratar ordet abstrakt betydningen. Dine andre programmerere vil også bli veldig overrasket over å se dette :/ Når det er sagt, hvis en metode er merket som abstrakt, må hver etterkommerklasse implementere den eller bli erklært som abstrakt. Ellers vil kompilatoren gi en feil. Selvfølgelig kan hver klasse bare arve én abstrakt klasse, så det er ingen forskjell mellom abstrakte og vanlige klasser når det gjelder arv. Det spiller ingen rolle om vi arver en abstrakt klasse eller en vanlig - det kan bare være én overordnet klasse.

Hvorfor Java ikke har flere klassearv

Vi har allerede sagt at det ikke er noen multippel arv i Java, men vi har ikke fordypet oss i hvorfor. La oss prøve å gjøre det nå. Faktum er at hvis Java hadde multippel arv, ville ikke barneklasser kunne bestemme hvilken oppførsel de skulle velge. La oss si at vi har to klasser: Toasterog NuclearBomb:

public class Toaster {
  
  
 public void on() {

       System.out.println("The toaster is on. We're toasting!");
   }
  
   public void off() {

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


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
Som du kan se, har begge klassene en on()metode. For brødristeren begynner metoden å lage toast, men når det gjelder atombomben, utløser den en eksplosjon. Uh-oh :/ Tenk deg nå at du har bestemt deg (ikke spør meg hvorfor!) for å lage noe midt i mellom. Her er klassen din: MysteriousDevice! Denne koden vil selvfølgelig ikke fungere. Vi presenterer det ganske enkelt som et eksempel på "hva som kan ha vært":

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 toast or a nuclear apocalypse?
   }
}
La oss se hva vi har. Den mystiske enheten stammer fra både Toaster og NuclearBomb på samme tid. Begge har en on()metode. Som et resultat er det ikke klart hvilken implementering som skal utføres hvis vi kaller on()på et MysteriousDeviceobjekt. Objektet vil ikke forstå. Og for å toppe det hele, har ikke NuclearBomb en off()metode, så hvis vi ikke gjetter riktig, så vil det være umulig å slå av enheten. Konkrete eksempler på abstrakte klasser i Java - 2Denne "misforståelsen", når det er uklart hvilken oppførsel som skal utføres, er nettopp grunnen til at Javas skapere avviste multippel arv. Når det er sagt, vil du lære at Java-klasser kan implementere mange grensesnitt.