Главная » Java » Абстрактные классы и методы

0

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

Абстракция оказывается полезной, когда некоторое поведение характерно для большинства или всех объектов данного класса, но некоторые аспекты имеют смысл лишь для ограниченного круга объектов, не составляющих суперкласса. В Java такие классы объявляются с ключевым словом abstract, и каждый метод, не реализованный в классе, также объявляется abstract. (Если все, что вам требуется, — это определить набор методов, которые будут где-то поддерживаться, но не предоставлять для них реализации, то вместо абстрактных классов, видимо, лучше воспользоваться интерфейсами, описанными в главе 4.)

Допустим, вы хотите создать инфраструктуру для написания кода, который будет во время выполнения программы измерять определенные показатели. Реализация такого класса может учитывать, как происходит измерение, но вы не знаете заранее, какой именно показатель будет измеряться. Большинство абстрактных классов следует именно этому принципу: для конкретной работы, выполняемой классом, необходимо, чтобы кто- то предоставил недостающую часть. В нашем примере таким недостающим звеном становится фрагмент программы, выполняющий измерения. Вот как может выглядеть соответствующий  класс:

abstract class Benchmark {

abstract void benchmark();

public long repeat(int count) {

long start = System.currentTimeMillis();

for (int i = 0; i < count; i++)

benchmark();

return (System.currentTimeMillis() — start);

}

}

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

Метод repeat предоставляет общую схему для проведения измерений. Он знает, как ему вызвать процедуру измерения count раз через равные интервалы времени. Если хронометраж должен быть более сложным (например, необходимо измерить время каждого запуска и вычислить статистику отклонения от среднего значения), метод можно усовершенствовать,  что никак не отразится на реализации процедуры измерений в расширенном классе.

Абстрактный метод benchmark должен быть реализован в каждом подклассе, который не является абстрактным. Именно по этой причине в классе отсутствует реализация, есть лишь объявление. Приведем пример простейшего расширения класса Benchmark:

class MethodBenchmark extends Benchark {

void benchmark() {

}

public static void main(String[] args) {

int count = Integer.parseInt(args[0]);

long time = new MethodBenchmark().repeat(count); System.out.println(count + “ methods in ” +

time + “ milliseconds”);

}

}

Данный класс использует benchmark для определения времени, затраченного на вызов метода. Теперь вы можете провести хронометраж, запустив приложение MethodBenchmark,  сообщив ему количество повторений теста. Значение передается в

программу в виде аргумента-строки,  из которого оно извлекается методом parseInt класса

Integer, как описано в разделе “Преобразование строк”.

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

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

Упражнение 3.6

Напишите новый класс, который измеряет что-нибудь другое — например, время,

затраченное на выполнение цикла от 0 до значения, переданного в виде параметра.

Упражнение 3.7

Измените класс Vehicle так, чтобы он содержал ссылку на объект EnergySource (источник энергии), ассоциируемый с Vehicle внутри конструктора. Класс EnergySource должен быть абстрактным, поскольку состояние заполнения для объекта GasTank (бензобак) должно отмечаться иначе, нежели для объекта Battery (аккумулятор). Включите в EnergySource

абстрактный метод empty и реализуйте его в классах GasTank и Battery. Включите в

Vehicle метод start, который бы проверял состояние источника энергии в начале поездки.

Источник: Арнольд К., Гослинг Д. – Язык программирования Java (1997)

По теме:

  • Комментарии