1. Gemensam basklass

Idag njuter vi av ett smörgåsbord med intressanta ämnen. Kommer du ihåg när vi introducerade ChessItembasklassen för att förenkla alla klasser som representerar schackpjäser? Jag hoppas det 🙂

Föreställ dig nu att varje bit har en draw()metod som hanterar att rita den på skärmen. Du anropar draw()metoden, och pjäsen ritar sig själv vid sina nuvarande koordinater. Det skulle vara bekvämt att flytta denna metod till basklassen.

Om draw()metoden var i basklassen ChessItem, skulle vi kunna åsidosätta den i pjäsklasserna och skriva elegant kod så här:

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

Genom att introducera ChessItembasklassen kunde vi avsevärt förenkla koden: det finns inget behov av att anropa metoderna för varje klass separat, vi kan enkelt lagra alla objekt i en enda samling, etc.

Men här är en intressant fråga: vad ska metoden draw()som deklareras direkt i ChessItemklassen rita på skärmen? Det finns trots allt ingen sådan pjäs i schack, så det finns inget att dra.

Det är helt rätt. Dessutom är det ingen mening att skapa ChessItemobjekt direkt. Det är inte ett schackpjäs, utan snarare bara en abstraktion - en klass som vi skapade för vår bekvämlighet. Så här fungerar abstraktion i OOP : vi flyttar viktiga data och metoder (de som delas av alla delar) till en basklass och behåller deras skillnader i separata underklasser.


2. Abstrakta klasser

Abstrakta klasser

För sådana situationer har Java en speciell typ av klass: den abstrakta klassen . De är utformade för att göra det enklare för programmerare att arbeta med liknande klasser och minska mängden duplicerad kod i dem.

Här är tre saker att veta om abstrakta klasser.

Metod utan implementering

En abstrakt klass kan ha en metoddeklaration utan implementering. Det är just detta som gör metoden abstrakt. Metodens kropp ersätts helt enkelt med semikolon. Och före namnet på metoden skriver vi nyckelordet abstract. Exempel:

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 klass

Varje metod utan implementering är markerad med det abstrakta nyckelordet. Om en klass ens har en abstrakt metod markeras klassen också med nyckelordet abstract.

Förbud mot att skapa föremål

Du kan inte skapa objekt av en abstrakt klass . Sådan kod kommer helt enkelt inte att kompilera.

Koda Beskrivning
ChessItem item = new ChessItem();
item.draw();
Denna kod kompilerar inte :
ChessItem item = new Queen();
item.draw();
Men du kan göra det här

Ärver en abstrakt klass

Om din klass ärver en abstrakt klass måste du åsidosätta alla nedärvda abstrakta metoder, dvs du måste skriva en implementering för dem. Annars måste din klass också förklaras abstrakt.

Om en klass ens har en oimplementerad metod deklarerad direkt i sig eller ärvd från en överordnad klass, anses klassen vara abstrakt.

Och varför är allt detta nödvändigt? Varför behövs abstrakta klasser? Går det inte att använda vanliga istället? Och istället för abstrakta metoder, kunde vi inte bara skriva två tomma parenteser som metodkroppen?

Vi kunde. Men dessa begränsningar är besläktade med privatemodifieraren. Vi använder det privata nyckelordet för att medvetet förhindra andra programmerare från att direkt komma åt data och för att tvinga dem att endast använda våra offentliga metoder när de skriver sina klasser.

Det är samma sak med abstrakta klasser. Författaren till en abstrakt klass vill inte att objekt i klassen ska skapas. Istället förväntar sig författaren att abstrakta metoder ärvs från den abstrakta klassen och sedan åsidosätts.

Fördelarna med detta tillvägagångssätt är lätt uppenbara i stora projekt. Ju fler klasser du har, desto tydligare behöver du avgränsa deras roller. Du kommer att se fördelarna med detta tillvägagångssätt inom en snar framtid. Allt går igenom detta.