1. Общ базов клас

Днес ще се насладим на голямо разнообразие от интересни теми. Спомняте ли си, когато въведохме ChessItemбазовия клас, за да опростим всички класове, представляващи шахматни фигури? Надявам се 🙂

Сега си представете, че всяко парче има draw()метод, който се справя с рисуването му на екрана. Извиквате draw()метода и парчето се рисува в текущите си координати. Би било удобно този метод да се премести в базовия клас.

Ако draw()методът беше в базовия клас ChessItem, тогава бихме могли да го заменим в класовете на фигурите и да напишем елегантен code като този:

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

С въвеждането на ChessItemбазовия клас успяхме значително да опростим codeа: няма нужда да извикваме методите на всеки клас поотделно, можем лесно да съхраняваме всички обекти в една колекция и т.н.

Но ето един интересен въпрос: Howво трябва да изобрази на екрана draw()методът, деклариран директно в класа? ChessItemВ края на краищата в шаха няма такава фигура, така че няма Howво да се направи.

Точно така. Нещо повече, няма смисъл да се създават ChessItemобекти директно. Това не е шахматна фигура, а по-скоро просто абстракция — клас, който създадохме за наше удобство. Ето How работи абстракцията в ООП : преместваме важни данни и методи (тези, които се споделят от всички части) в базов клас и запазваме техните разлики в отделни класове наследници.


2. Абстрактни класове

Абстрактни класове

За такива ситуации Java има специален вид клас: абстрактен клас . Те са предназначени да улеснят програмистите при работа с подобни класове и да намалят количеството дублиран code в тях.

Ето три неща, които трябва да знаете за абстрактните класове.

Метод без реализация

Абстрактен клас може да има декларация на метод без имплементация. Точно това прави метода абстрактен. Тялото на метода просто се заменя с точка и запетая. И преди името на метода пишем ключовата abstractдума. Пример:

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.
}

Абстрактен клас

Всеки метод без реализация е маркиран с абстрактната ключова дума. Ако даден клас има дори един абстрактен метод, класът също се маркира с abstractключовата дума.

Забрана за създаване на обекти

Не можете да създавате обекти от абстрактен клас . Такъв code просто няма да се компorра.

Код Описание
ChessItem item = new ChessItem();
item.draw();
Този code не се компorра :
ChessItem item = new Queen();
item.draw();
Но можете да направите това

Наследяване на абстрактен клас

Ако вашият клас наследи абстрактен клас, тогава трябва да замените всички наследени абстрактни методи, т.е. трябва да напишете имплементация за тях. В противен случай самият ви клас също ще трябва да бъде обявен за абстрактен.

Ако един клас има дори един неимплементиран метод, деклариран директно в него or наследен от родителски клас, тогава класът се счита за абстрактен.

И защо е необходимо всичко това? Защо са необходими абстрактни класове? Не може ли instead of тях да се използват обикновени? И instead of абстрактни методи, не можехме ли просто да напишем две празни къдрави скоби като тяло на метода?

Бихме могли. Но тези ограничения са подобни на privateмодификатора. Използваме ключовата дума private, за да попречим умишлено на други програмисти да имат директен достъп до данни и да ги принудим да използват само нашите публични методи, когато пишат своите класове.

Същото е и с абстрактните класове. Authorът на абстрактен клас не желае да се създават обекти от класа. Вместо това авторът очаква абстрактните методи да бъдат наследени от абстрактния клас и след това да бъдат заменени.

Предимството на този подход е очевидно при големи проекти. Колкото повече класове имате, толкова по-ясно трябва да очертаете техните роли. Ще видите ползата от този подход в близко бъдеще. Всяко нещо минава през това.