Top.Mail.Ru

Перечень уроков по Java

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

Базовый класс, объекты которого никогда не могут быть созданы, называется абстрактным классом. Единственная цель существования абстрактного класса  – быть родительским классом к производным классам, объекты которых будут реализованы.

 

 Основные свойства:

  • ¨ Метод называется абстрактным, если при определении метода не задана реализация метода. Такой метод обозначается спецификатором  abstract, например,

abstract public double Area ();

Обратите внимание, в методе не указывается тело метода (фигурные скобки). Ключевое слово abstract может стоять как до, так и после модификатора доступа.

  • ¨ Класс называется абстрактным, если он имеет хотя бы один абстрактный метод и в заголовке спецификатор abstract, например,

public abstract class Figura {

Ключевое слово abstract может стоять как до, так и после модификатора доступа.

  • ¨ Наследник абстрактного класса должен реализовать все абстрактные методы родителя.
  • ¨ Абстрактный класс может содержать обычные поля и методы.

 

Цель Наследование – заимствование реализации, а в классе, где нет реализаций, заимствовать нечего. Тогда зачем?

 

Назначение абстрактных классов

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

  1. Указывают наследникам направление, в котором должна быть выполнена  доработка методов.
  2. Не передавая реализации методов, навязывает классу-наследнику определенные черты.

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

 Такая ситуация возникла в примере с геометрическими фигурами (полиморфизм). В базовом классе  Figure мы не могли записать общий метод вычисления площади фигур, потому что алгоритмы  подсчета площади фигур разные. Пришлось записать несколько искусственный  общий метод  вычисления площади Area(), содержимое которого было:

  

        public double Area (){

            return 0;

        }

Устраним эту искусственность. Вернемся к классу Figura и запишем этот класс как абстрактный.  Методы public double Area()  и  public void PrintArea() объявим абстрактными, т.е. методы подсчета площади для всех фигур  и печати  без реализации. Классы  Circle, Rect, Trap обязаны будут каждый для себя записать конкретную реализацию этого метода. Другими словами мы классам Circle, Rect, Trap навязываем определенные методы, и они не могут забыть об этих методах.

Для демонстрации того, что базовый класс может содержать обычные поля и методы, дополним класс Figure  полем name  -  в нем будем хранить имя класса и методом PrintName() -  для печати имени класса.

Вот листинг.

 

public abstract class Figura {

      private String name;   //обычное поле класса

      abstract public double Area ();

      abstract  public void PrintArea();

     

//конструктор

      public Figura(String Name)

      {

         name=Name;

      }

//обычный метод

      public void PrintName()

      {

          System.out.println ("Имя класса: " + name);

      }

}

 

Public class Circle extends Figura{

    int a;

     public  Circle (String Name,int A)

    {  //вызывается конструктор базового класса

        super(Name);

        a=A;

    }

    public double Area (){

            return Math.PI*a*a;

    }

    public void PrintArea(){

    System.out.println("Площадь круга: "+ Area());

    }   

}

 

Поскольку класс Circle является производным от класса Figura, то класс Circle вынужден записать конкретную реализацию  методов Area () и PrintArea().

 

 public class Rect extends Figura {

     int a;

     int b;

    public  Rect (String Name,int A, int B)

    { super(Name);

        a=A;

        b=B;

    }

    @Override

    public double Area (){

               return a*b;

    }

    public void PrintArea(){

    System.out.println("Площадь прямоугольника: "+ Area());

    }

}

 

 

public class Trap extends Figura{

     int a;

     int b;

     int h;

    

    public  Trap (String Name, int A, int B, int H)

    {  super(Name);

        a=A;

        b=B;

        h=H;

    }

    public double Area (){

              return (a + b)*h/2;

    }

   

    public void PrintArea(){

    System.out.println("Площадь трапеции: "+ Area());

    }

 }

public static void main(String[] args) {

         //создаем массив ссылок на базовый класс

        Figura [] f = new Figura [5];

        //создаем объекты, ссылки на объеты храним

        //в массиве ссылок базового класса

         f[0]= new Circle("Круг", 1);

         f[1]= new Rect("Прямоугольник",1,1);

         f[2]= new Trap("Трапеция",1,1,1);

         f[3]= new Circle("Круг",1);

         f[4]= new Rect("Прямоугольник",1,1);

        

         //работает механизм полимофизма

         for(int i=0; i<f.length; i++){

                 f[i].PrintName();

                 f[i].PrintArea();

         }

    }

}

  

Будет выведено:

Имя класса: Круг
Площадь круга: 3.141592653589793
Имя класса: Прямоугольник
Площадь прямоугольника: 1.0
Имя класса: Трапеция
Площадь трапеции: 1.0
Имя класса: Круг
Площадь круга: 3.141592653589793
Имя класса: Прямоугольник
Площадь прямоугольника: 1.0