В каких же случаях создавать вложенные классы? В теории ООП вопрос о создании вложенных классов решается при рассмотрении отношений "быть частью" и "являться".
Отношения "быть частью" и "являться"
Теперь у нас появились две различные иерархии классов. Одну иерархию образует наследование классов, другую — вложенность классов.
Определив, какие классы будут написаны в вашей программе, и сколько их будет, подумайте, как спроектировать взаимодействие классов? Вырастить пышное генеалогическое дерево классов-наследников или расписать матрешку вложенных классов?
Теория ООП советует прежде всего выяснить, в каком отношении находятся ваши классы P и Q — в отношении "класс Q является экземпляром класса P" ("a class Q is a class р") или в отношении "класс Q — часть класса P" ("a class Q has a class P").
Например: "Собака является животным" или "Собака — часть животного"? Ясно, что верно первое отношение "is-a", поэтому мы и определили класс Dog как расширение класса Pet.
Отношение "is-a" — это отношение "обобщение-детализация", отношение большей или меньшей абстракции, и ему соответствует наследование классов.
Отношение "has-a" — это отношение "целое-часть", ему соответствует вложение.
Обратный вызов (callback) широко распространен в программировании. При обратном вызове программист задает действия, которые должны выполняться всякий раз, когда происходит некоторое событие. Например, можно задать действие, которое должно быть выполнено, если будет нажата конкретная кнопка или выбран определенный пункт меню.
Рассмотрим простую ситуацию. Пакет java.swing содержит класс Timer, который можно использовать для отсчета интервалов времени. Например, если в программе предусмотрены часы, то с помощью класса Timer, можно отсчитывать каждую секунду и обновлять циферблат часов. Устанавливая таймер, мы задаем интервал времени и указываем, что должно произойти по его истечении.
Как указать таймеру, что он должен делать? Во многих языках программирования задается имя функции, которую таймер должен периодически вызывать.
Классы из стандартной библиотеки языка Java используют объектно-ориентированный подход. Программист должен передать таймеру объект некоторого класса. После этого таймер вызывает один из методов данного объекта.
Передача объекта – более гибкий механизм, чем вызов функций, поскольку объект может нести с собой дополнительную информацию. Значит, таймер должен знать, какой метод он должен вызвать. Для этого таймеру нужно указать объект класса, реализующего интерфейс ActionListenerиз пакета java.awt.event.
Воткаквыглядитэтотинтерфейс
public interface ActionListener
{
void actionPerformed (ActionEvent event);
}
По истечении заданного интервала времени таймер вызывает метод actionPerformed.
Рассмотрим пример. Пусть нужно каждые 10 секунд выводить на экран сообщение «Текущее время …», сопровождаемое звуковым сигналом. Для этого необходимо определить класс, реализующий интерфейс ActionListener. Затем поместить операторы, которые нужно выполнить, внутрь методаactionPerformed.
class Timerprinter implements ActionListener
{
public voidactionPerformed(ActionEvent event)
{
Date now= new Date( );
System.out.println(“Текущеевремя:» + now);
Toolkit.getDefaultToolkit( ).bеep( );
}
}
Затем следует создать объект данного класса и передать его конструктору класса Timer.
ActionListener listener=new TimerPrinter ( );
Timer t=new Timer (10000, listener);
Первый параметр конструктора Timer представляет собой интервал времени между точками отсчета, измеренный в миллисекундах. Сообщение должно выдаваться на экран каждые десять секунд.
Второй параметр является объектом класса ActionListener
Запуск таймера
t.start( );
Каждые 10 секунд на экране будет появляться сообщение о текущем времени. В листинге 6.2. приведена программа, реализующая описанный алгоритм.
importjava.awt.*;
import java.awt.event*;
import javax.swing.*;
import javax.swing.Timer*; // чтобыразрешитьконфликтсклассом javax.util.Timer
public class TimerTest
{
public static void main (string[ ] args)
{
ActionListener listener= new TimerPrinter ( );
// Создаеттаймер, вызывающийблоккаждые 10 сек.
Timer t=new Timer (10000, listener);
t.start( );
JOptionPаne.showMessageDialog(null,”Выход?”);
System.exit(0);
}
}
class Timerprinter implements ActionListener
{
public voidactionPerformed(ActionEvent event)
{
Date now= new Date( );
System.out.println(“Текущеевремя:» + now);
Toolkit.getDefaultToolkit( ).bеep( );
}
}