Освой Java играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Абстрактные классы и методы

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

Абстрактный метод не завершён. Он состоит только из объявления и не имеет тела:

abstract void yourMethod();

По сути, мы создаём шаблон метода. Например, можно создать абстрактный метод для вычисления площади фигуры в абстрактном классе Фигура. А все другие производные классы от главного класса могут уже реализовать свой код для готового метода. Ведь площадь у прямоугольника и треугольника вычисляется по разным алгоритмам и универсального метода не существует.

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

Можно создавать класс с ключевым словом abstract даже, если в нем не имеется ни одного абстрактного метода. Это бывает полезным в ситуациях, где в классе абстрактные методы просто не нужны, но необходимо запретить создание экземпляров этого класса.

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

Создавать объект на основе абстрактного класса нельзя.


// нельзя. даже не пытайтесь
AbstractClass abstractClass = new AbstractClass();

Абстрактный класс не может содержать какие-либо объекты, а также абстрактные конструкторы и абстрактные статические методы. Любой подкласс абстрактного класса должен либо реализовать все абстрактные методы суперкласса, либо сам быть объявлен абстрактным. Короче, я сам запутался. Пойду лучше кота поглажу.

Я вернулся. Давайте напишем пример для абстрактного класса.

Допустим, мы хотим создать абстрактный класс СферическийКонь и не менее идиотский класс СферическийКоньВВакууме, наследующий от первого класса.


package ru.alexanderklimov.expresscourse;

public abstract class SphericalHorse {
    // абстрактный метод ржать()
    abstract void neigh();

    // абстрактный класс может содержать и обычный метод
    void gallop() {
        System.out.println("Куда прёшь?");
    }
}

class SphericalHorseInVacuum extends SphericalHorse {

}

Когда вы напишете такой код, то студия подчеркнёт второй класс красной волнистой линией и предложит реализовать обязательный метод, который определён в абстрактном классе.

Abstract

Abstract

Соглашаемся и дописываем в созданную заготовку свой код для метода.


@Override
void neigh() {
    System.out.println("Чё ты ржёшь?");
}

В главной активности напишем код для щелчка кнопки.


public void onClick(View view) {
    SphericalHorseInVacuum horse = new SphericalHorseInVacuum();
    horse.neigh(); // на основе абстрактного метода
    horse.gallop(); // обычный метод
}

Обратите внимание, что абстрактный класс может содержать не только абстрактные, но и обычные методы.

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


// абстрактный класс Фигура
abstract class Figure {
    double dim1;
    double dim2;
    
    Figure(double a, double b) {
        dim1 = a;
        dim2 = b;
    }
    
    // абстрактный метод для вычисления площади
    abstract double area();
}

// Клас Треугольник
class Triangle extends Figure {
    Triangle(double a, double b) {
        super(a, b);
    }
    
    // переопределяем метод
    double area() {
        return dim1 * dim2 / 2;
    }
}

// В активности
public void onClick(View view) {
    // Figure figure = new Figure(10, 10); // так нельзя
    Triangle triangle = new Triangle(10, 8);

    Figure figure; // так можно, так как объект мы не создаем
    figure = triangle;
    mInfoTextView.append("Площадь равна " + figure.area());
}

Фигура - это абстрактное понятие и мы не можем создать универсальный метод для вычисления площади. Поэтому мы создаём другой класс Треугольник и пишем код, вычисляющий площадь треугольника (загляните в учебник геометрии). Также вы можете создать новый класс Прямоугольник и написать свой код для вычисления площади этой фигуры.

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

Кот - понятие тоже абстрактное. А вот ваш любимец Васька или Мурзик уже конкретный шерстяной засранец. По запросу "abstract cat" мне выдало такую картинку. Всегда интересовал вопрос, где художники берут такую травку? (это был абстрактный вопрос).

Abstract cat

Реклама