Главная » Java » Методы и классы abstract Java

0

Здесь мы расскажем еще об одном чрезвычайно полезном инструменте объектно-ориентированного программирования – о концепции абстрактного (abstract) класса. Используя ее на практике, вы сможете объявить класс, представив только часть его реализации и заранее предусмотрев возможность переопределения всех или некоторых методов в производных классах. До сих пор же мы имели дело только с конкретными (concrete) классами, в которых каждый метод был объявлен полностью.

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

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

 

 

abstract class Benchmark {

abstract void benchmark();

public final long repeat(int count) {

long start = System.currentTimeMillis();

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

 benchmark() ;

return (system.currentTimeMillis() – start);

}

}

 

 

 

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

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

Абстрактный метод benchmark должен быть переопределен в любом производном классе, если только тот не помечен как abstract. Ниже приведен пример возможного расширенного класса.

 

class MethodBenchmark extends Benchmark {

 

/** метод ничего не выполняет, а просто возвращает управление

  */

void benchmark() { }

 

public static void main(String[] args) {

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

 

long time = new MethodBenchmark().repeat(count);

 System.out.println(count + "вызовов в течение" +

time + " миллисекунд");

}

}

 

В методе main реализован код, позволяющий оценить величину промежутка времени, требуемого для циклического обращения к пустому методу benchmark. Пользователь может управлять процессом, задавая необходимое количество итераций тестирования в виде аргумента командной строки программы. Аргумент типа String преобразуется в числовую форму с помощью статического метода parseInt класса Integer (за подробностями обращайтесь к разделу 9.5 на странице 233).

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

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

 

Упражнение 3.5. Создайте еще один класс, расширяющий класс Benchmark и позволяющий выполнить какие-либо иные измерения.

 

Упражнение 3.6. Обратитесь к примеру, связанному с классом Vehiclе. Создайте абстрактный класс Energysource (источник энергии) с абстрактным методом empty, предназначенным для определения величины текущего запаса энергии, и

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

 

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

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