Hoi! Laten we het hebben over abstracte klassen in Java.Concrete voorbeelden van abstracte klassen in Java - 1

Waarom worden klassen "abstract" genoemd?

Je herinnert je waarschijnlijk wat abstractie is - we hebben het eerder besproken :) Als je het bent vergeten, geen zorgen. Onthoud dat het een OOP-principe is dat zegt dat je bij het ontwerpen van klassen en het maken van objecten alleen de hoofdeigenschappen van de entiteit moet weergeven en secundaire eigenschappen moet negeren. Als we bijvoorbeeld een SchoolTeacherklas ontwerpen, is lengte waarschijnlijk geen noodzakelijke eigenschap van een leraar. Dit kenmerk is inderdaad niet belangrijk voor een leraar. Maar als we een BasketballPlayerklasse creëren, dan is lengte een van de belangrijkste kenmerken. Nou ja, een abstracte klasseis het meest abstracte, "ruwe werkstuk" voor een groep toekomstige klassen. Het werkstuk kan niet direct worden gebruikt - het is te "ruw". Maar het definieert een bepaalde karakteristieke toestand en gedrag dat toekomstige klassen - de afstammelingen van de abstracte klasse - zullen hebben.

Voorbeelden van abstracte klassen in Java

Beschouw een eenvoudig voorbeeld met auto's:

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;
   }
}
Zo ziet de eenvoudigste abstracte klasse eruit. Zoals je kunt zien, niets bijzonders :) Waarom zouden we dit nodig hebben? Ten eerste geeft het de meest abstracte beschrijving van de entiteit die we nodig hebben: een auto. Het abstracte sleutelwoord betekent hier iets. In de echte wereld bestaat er niet zoiets als "zomaar een auto". Er zijn vrachtwagens, raceauto's, sedans, coupés en SUV's. Onze abstracte klasse is gewoon een "blauwdruk" die we later zullen gebruiken om specifieke autoklassen te creëren.

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!");
   }
  
}
In veel opzichten komt dit overeen met waar we het over hadden in de lessen over erfrecht. Alleen in dat geval hadden we een Carklasse waarvan de methoden niet abstract waren. Maar zo'n oplossing heeft verschillende nadelen die in abstracte klassen zijn vastgelegd. Allereerst kan er geen instantie van een abstracte klasse worden gemaakt:

public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
De maker van Java heeft deze "functie" met opzet gemaakt. Onthoud nogmaals: een abstracte klasse is slechts een blauwdruk voor toekomstige "gewone" klassen . Je hebt toch geen kopieën van een blauwdruk nodig? Evenzo is het niet nodig om instanties van een abstracte klasse te maken :) En als de Carklasse niet abstract zou zijn, dan zouden we er gemakkelijk instanties van kunnen maken:

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.
   }
}
Op dit moment heeft ons programma een soort onbegrijpelijke auto. Het is geen vrachtwagen, geen raceauto en geen sedan, maar het is niet echt duidelijk wat het is. Het is "gewoon een auto" die in werkelijkheid niet bestaat. Hetzelfde voorbeeld kan worden gegeven met dieren. Stel je voor dat je programma Animalobjecten had (" alleen dieren "). Het is niet duidelijk wat voor soort het is, tot welke familie het behoort of welke kenmerken het heeft. Het zou vreemd zijn om er een in een programma te zien. Er zijn geen "zomaar dieren" in de natuur. Alleen honden, katten, vossen, mollen, enz. Abstracte klassen redden ons van " slechts objecten ". Ze geven ons basisstatus en gedrag. Zo moeten alle auto's een model , kleur en topsnelheid hebbenen ze moeten ook gas kunnen geven en kunnen remmen . Dat is het. Het is een algemene abstracte blauwdruk die je later zult gebruiken om de klassen te ontwerpen die je nodig hebt. Opmerking: de twee methoden in de abstracte klasse zijn ook abstract , wat betekent dat ze helemaal geen implementatie hebben. De reden is dezelfde: abstracte klassen creëren geen "standaardgedrag" voor "alleen auto's". Ze geven gewoon aan wat elke auto moet kunnen. Dat gezegd hebbende, als je standaardgedrag nodig hebt, kun je methoden in een abstracte klasse implementeren. Java verbiedt dit niet:

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();
   }
}
Console-uitvoer:
Accelerating!
Zoals je kunt zien, hebben we de ene methode geïmplementeerd in de abstracte klasse, maar de andere niet. Het resultaat is dat het gedrag van onze Sedanklasse in twee delen is verdeeld: als we zijn gas()methode aanroepen, wordt het gedrag "opgehaald" uit de abstracte Carbovenliggende klasse en implementeren we de brake()methode in de Sedanklasse. Dat is superhandig en flexibel. Maar onze klas is nu toch niet zo abstract meer ? Het implementeerde tenslotte de helft van de methoden. Het feit is - en dit is een heel belangrijk kenmerk - een klasse is abstract als zelfs maar één van zijn methoden abstract is. Eén methode van twee, of één van duizend - het maakt niet uit. We zouden zelfs alle methoden kunnen implementeren, zonder abstract te laten. Het resultaat zou een abstracte klasse zijn zonder abstracte methoden. In principe is dat mogelijk — de compiler zal geen fouten genereren — maar het is beter om dit niet te doen, omdat het het woord abstract zijn betekenis ontneemt. Je collega-programmeurs zullen ook erg verrast zijn om dit te zien :/ Dat gezegd hebbende, als een methode als abstract is gemarkeerd, moet elke afstammende klasse deze implementeren of als abstract worden gedeclareerd. Anders geeft de compiler een foutmelding. Natuurlijk kan elke klasse slechts één abstracte klasse overerven, dus er is geen verschil tussen abstracte en reguliere klassen in termen van overerving. Het maakt niet uit of we een abstracte klasse of een gewone klasse erven — er kan maar één bovenliggende klasse zijn.

Waarom Java geen overerving van meerdere klassen heeft

We hebben al gezegd dat er geen meervoudige overerving is op Java, maar we hebben ons niet echt verdiept in waarom. Laten we dat nu proberen te doen. Het feit is dat als Java meervoudige overerving zou hebben, onderliggende klassen niet zouden kunnen beslissen welk gedrag ze moeten kiezen. Laten we zeggen dat we twee klassen hebben: Toasteren 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!");
   }
}
Zoals je kunt zien, hebben beide klassen een on()methode. Voor de broodrooster begint de methode met het maken van toast, maar in het geval van de atoombom veroorzaakt het een explosie. Uh-oh :/ Stel je nu voor dat je hebt besloten (vraag me niet waarom!) om er iets tussenin te maken. Hier is je klas: MysteriousDevice! Deze code werkt natuurlijk niet. We presenteren het gewoon als een voorbeeld van "wat had kunnen zijn":

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?
   }
}
Laten we eens kijken wat we hebben. Het mysterieuze apparaat is tegelijkertijd afgeleid van zowel Toaster als NuclearBomb. Beiden hebben een on()methode. Hierdoor is het niet duidelijk welke implementatie uitgevoerd moet worden als we on()een MysteriousDeviceobject aanroepen. Het object zal het niet begrijpen. En als klap op de vuurpijl heeft NuclearBomb geen off()methode, dus als we niet goed raden, is het onmogelijk om het apparaat uit te schakelen. Concrete voorbeelden van abstracte klassen in Java - 2Dit "misverstand", wanneer het onduidelijk is welk gedrag moet worden uitgevoerd, is precies de reden waarom de makers van Java meervoudige overerving hebben afgewezen. Dat gezegd hebbende, zult u leren dat Java-klassen vele interfaces kunnen implementeren.