1. Felles grunnklasse

I dag skal vi nyte et smørbrød med interessante emner. Husker du da vi introduserte ChessItembasisklassen for å forenkle alle klassene som representerer sjakkbrikker? Jeg håper det 🙂

Tenk deg nå at hver brikke har en draw()metode som håndterer å tegne den på skjermen. Du kaller draw()metoden, og stykket tegner seg selv ved sine nåværende koordinater. Det ville være praktisk å flytte denne metoden til basisklassen.

Hvis draw()metoden var i ChessItem-basisklassen, kunne vi overstyre den i brikkeklassene og skrive elegant kode slik:

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 å introdusere ChessItembasisklassen var vi i stand til å forenkle koden betydelig: det er ikke nødvendig å kalle metodene til hver klasse separat, vi kan enkelt lagre alle objektene i en enkelt samling, etc.

Men her er et interessant spørsmål: hva skal metoden draw()deklarert direkte i ChessItemklassen tegne på skjermen? Tross alt er det ingen slik brikke i sjakk, så det er ingenting å trekke.

Det er helt riktig. Dessuten gir det ingen mening å lage ChessItemobjekter direkte. Det er ikke et sjakkstykke, men bare en abstraksjon – en klasse som vi har laget for å gjøre det lettere. Slik fungerer abstraksjon i OOP : vi flytter viktige data og metoder (de som deles av alle deler) til en basisklasse, og beholder forskjellene deres i separate etterkommerklasser.


2. Abstrakte klasser

Abstrakte klasser

For slike situasjoner har Java en spesiell type klasse: den abstrakte klassen . De er designet for å gjøre det enklere for programmerere å jobbe med lignende klasser og redusere mengden duplisert kode i dem.

Her er tre ting å vite om abstrakte klasser.

Metode uten implementering

En abstrakt klasse kan ha en metodeerklæring uten en implementering. Det er nettopp dette som gjør metoden abstrakt. Metodekroppen erstattes ganske enkelt med semikolon. Og før navnet på metoden skriver vi nøkkelordet 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 uten implementering er merket med det abstrakte nøkkelordet. Hvis en klasse har én abstrakt metode, er klassen også merket med nøkkelordet abstract.

Forbud mot å lage gjenstander

Du kan ikke opprette objekter av en abstrakt klasse . Slik kode vil rett og slett ikke kompilere.

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

Arve en abstrakt klasse

Hvis klassen din arver en abstrakt klasse, må du overstyre alle de nedarvede abstrakte metodene, dvs. du må skrive en implementering for dem. Ellers må selve klassen også erklæres abstrakt.

Hvis en klasse har til og med én uimplementert metode erklært direkte i den eller arvet fra en overordnet klasse, anses klassen som abstrakt.

Og hvorfor er alt dette nødvendig? Hvorfor trengs abstrakte klasser? Er det ikke mulig å bruke vanlige i stedet? Og i stedet for abstrakte metoder, kunne vi ikke bare skrive to tomme krøllete parenteser som metodekroppen?

Vi kunne. Men disse begrensningene er beslektet med privatemodifikatoren. Vi bruker det private nøkkelordet for bevisst å hindre andre programmerere fra å få direkte tilgang til data og for å tvinge dem til å bruke bare våre offentlige metoder når de skriver klassene sine.

Det er det samme med abstrakte klasser. Forfatteren av en abstrakt klasse vil ikke at objekter i klassen skal opprettes. I stedet forventer forfatteren at abstrakte metoder skal arves fra den abstrakte klassen og deretter overstyres.

Fordelen med denne tilnærmingen er lett synlig i store prosjekter. Jo flere klasser du har, jo tydeligere trenger du å avgrense rollene deres. Du vil se fordelene med denne tilnærmingen i nær fremtid. Hver ting går gjennom dette.