1. Fælles basisklasse

I dag vil vi nyde et smorgasbord med interessante emner. Kan du huske, da vi introducerede ChessItembasisklassen for at forenkle alle klasser, der repræsenterer skakbrikker? Det håber jeg 🙂

Forestil dig nu, at hver brik har en draw()metode, der håndterer at tegne den på skærmen. Du kalder draw()metoden, og stykket tegner sig selv ved sine nuværende koordinater. Det ville være praktisk at flytte denne metode til basisklassen.

Hvis draw()metoden var i ChessItem-basisklassen, så kunne vi tilsidesætte den i brikklasserne og skrive elegant kode som denne:

class ChessBoard
{
   public void drawAllChessItems()
   {
      // Add the pieces to the list
      ArrayList<ChessItem> items = new ArrayList<ChessItem>();
      items.add(new King());
      items.add(new Queen());
      items.add(new Bishop());

      // Draw them regardless of their type
      for(ChessItem item: items)
      {
         item.draw();
      }
   }
}

Ved at introducere ChessItembasisklassen var vi i stand til i høj grad at forenkle koden: der er ingen grund til at kalde metoderne for hver klasse separat, vi kan nemt gemme alle objekterne i en enkelt samling osv.

Men her er et interessant spørgsmål: hvad skal metoden, draw()der erklæres direkte i ChessItemklassen, tegne på skærmen? Der er jo ikke sådan en brik i skak, så der er ikke noget at trække.

Det er helt rigtigt. Hvad mere er, giver det ingen mening at skabe ChessItemobjekter direkte. Det er ikke et skakstykke, men derimod blot en abstraktion - en klasse, som vi har skabt for at gøre det nemmere. Sådan fungerer abstraktion i OOP : vi flytter vigtige data og metoder (dem, der deles af alle stykker) til en basisklasse og beholder deres forskelle i separate efterkommerklasser.


2. Abstrakte klasser

Abstrakte klasser

Til sådanne situationer har Java en særlig type klasse: den abstrakte klasse . De er designet til at gøre det lettere for programmører at arbejde med lignende klasser og reducere mængden af ​​duplikeret kode i dem.

Her er tre ting at vide om abstrakte klasser.

Metode uden implementering

En abstrakt klasse kan have en metodeerklæring uden en implementering. Det er netop det, der gør metoden abstrakt. Metodens krop er simpelthen erstattet med et semikolon. Og før navnet på metoden skriver vi nøgleordet abstract. Eksempel:

public abstract class ChessItem
{
   public int x, y; // Coordinates
   private int value; // The piece's value
   public int getValue() // Ordinary method that returns value field
   {
      return value;
   }

   public abstract void draw(); // Abstract method. The implementation is missing.
}

Abstrakt klasse

Hver metode uden implementering er markeret med det abstrakte nøgleord. Hvis en klasse kun har én abstrakt metode, er klassen også markeret med nøgleordet abstract.

Forbud mod at skabe genstande

Du kan ikke oprette objekter af en abstrakt klasse . En sådan kode vil simpelthen ikke kompilere.

Kode Beskrivelse
ChessItem item = new ChessItem();
item.draw();
Denne kode kompilerer ikke :
ChessItem item = new Queen();
item.draw();
Men du kan gøre dette

At arve en abstrakt klasse

Hvis din klasse arver en abstrakt klasse, så skal du tilsidesætte alle de nedarvede abstrakte metoder, dvs. du skal skrive en implementering til dem. Ellers skal din klasse også erklæres abstrakt.

Hvis en klasse har blot én uimplementeret metode erklæret direkte i sig eller arvet fra en overordnet klasse, så betragtes klassen som abstrakt.

Og hvorfor er alt dette nødvendigt? Hvorfor er der brug for abstrakte klasser? Er det ikke muligt at bruge almindelige i stedet? Og i stedet for abstrakte metoder, kunne vi ikke bare skrive to tomme krøllede parenteser som metodeteksten?

Vi kunne. Men disse begrænsninger er beslægtet med privatemodifikatoren. Vi bruger det private søgeord til bevidst at forhindre andre programmører i at få direkte adgang til data og til at tvinge dem til kun at bruge vores offentlige metoder, når de skriver deres klasser.

Det er det samme med abstrakte klasser. Forfatteren af ​​en abstrakt klasse ønsker ikke, at klassens objekter skal oprettes. I stedet forventer forfatteren, at abstrakte metoder nedarves fra den abstrakte klasse og derefter tilsidesættes.

Fordelen ved denne tilgang er let synlig i store projekter. Jo flere klasser du har, jo tydeligere skal du afgrænse deres roller. Du vil se fordelene ved denne tilgang i den nærmeste fremtid. Alt går igennem dette.