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

Сегодня просто день интересных тем. Помните ситуацию, когда мы ввели базовый класс ChessItem для упрощения всех классов шахматных фигур? Надеюсь, что да 🙂

Теперь представьте, что у каждой фигуры есть метод, который занимается ее отрисовкой на экране, например, draw(). Вызываешь метод draw(), и фигура сама себя рисует в своих текущих координатах. Удобно было бы вынести этот метод в базовый класс.

Если бы метод draw() был у базового класса ChessItem, можно было бы переопределить его в классах фигур и писать такой элегантный код:

class ChessBoard
{
   public void drawAllChessItems()
   {
      // добавляем фигуры в список
      ArrayList<ChessItem> items = new ArrayList<ChessItem>();
      items.add(new King());
      items.add(new Queen());
      items.add(new Bishop());

      // рисуем их независимо от типа
      for(ChessItem item: items)
      {
         item.draw();
      }
   }
}

Введение базового класса ChessItem помогает очень упростить код: не нужно вызывать методы каждого класса отдельно, можно легко хранить все объекты в одной коллекции и т.п.

Зато есть один интересный вопрос: а что должен отрисовывать на экране метод draw(), объявленный непосредственно в самом классе ChessItem? Ведь такой фигуры в шахматах нет, значит и рисовать нечего.

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


2. Абстрактные классы

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

Для такого случая в Java есть специальный тип классов — абстрактные классы. Они созданы для того, чтобы программисты могли упростить работу с похожими классами и уменьшить количество похожего кода в них.

Вот три вещи, которые стоит знать об абстрактных классах.

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

Абстрактный класс может содержать объявление метода без его реализации. Такой метод называется абстрактным. Вместо тела метода просто ставится точка с запятой. А перед названием метода пишется ключевое слово — abstract. Пример:

public abstract class ChessItem
{
   public int x, y; // координаты
   private int value; // «ценность» фигуры
   public int getValue() // обычный метод, возвращает значение value
   {
      return value;
   }

   public abstract void draw(); // абстрактный метод. Реализация отсутствует.
}

Абстрактный класс

Каждый метод без реализации помечается специальным ключевым словом abstract. Если в классе есть хоть один абстрактный метод, класс тоже помечается ключевым словом abstract.

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

Создавать объекты абстрактного класса нельзя. Такой код просто не скомпилируется.

Код Описание
ChessItem item = new ChessItem();
item.draw();
Этот код не скомпилируется
ChessItem item = new Queen();
item.draw();
А так можно

Наследование от абстрактного класса

Если вы наследовали свой класс от абстрактного класса, нужно переопределить все унаследованные абстрактные методы — написать для них реализацию. Иначе такой класс тоже придется объявить абстрактным.

Если в классе есть хотя бы один нереализованный метод, объявленный прямо в нем или унаследованный от класса-родителя, класс считается абстрактным.

И зачем это все нужно? Зачем нужны абстрактные классы? Разве нельзя вместо них использовать обычные? А вместо абстрактных методов просто писать две скобочки в качестве тела метода – {}?

Можно. Но эти ограничения сродни модификатору private. Мы специально запрещали с помощью private прямой доступ к данным, чтобы другие программисты и их классы пользовались только написанными нами public-методами.

То же и с абстрактным классом. Тот, кто написал этот класс, не хочет, чтобы создавались его объекты. Наоборот, он рассчитывает на то, что от его абстрактного класса будут наследоваться и переопределяться абстрактные методы.

Преимущество этого подхода проявляется в больших проектах. Чем больше классов, тем чётче приходится очерчивать их роли. Вы увидите преимущество этого подхода, и уже в ближайшем будущем. Все через это проходят.