Философия Java3
Шрифт:
// Здесь размещается код выключения // системы полива water = false;
}
public String toStringO {
return "Полив отключен";
}
}
private String thermostat = "День";
public class Thermostaticght extends Event {
public Thermostaticght(long delayTime) { super(delayTime);
}
public void actionO {
// Здесь размещается код управления оборудованием thermostat = "Ночь";
public String toStringO {
return "Термостат использует ночной режим";
}
}
public class ThermostatDay extends Event {
public ThermostatDay(long delayTime) { super(delayTime);
}
public void actionO {
//
}
public String toStringO {
return "Термостат использует дневной режим";
}
}
// Пример метода actionO, вставляющего
// самого себя в список событий.
public class Bell extends Event {
public Bell(long delayTime) { super(delayTime); } public void actionO {
addEvent(new Bell(delayTime));
}
public String toStringO { return "Бам!"; }
}
public class Restart extends Event { private Event[] eventList;
public Restartdong delayTime. Event[] eventList) { super(delayTime); this.eventList = eventList; for(Event e : eventList) addEvent(e);
}
public void actionO {
for(Event e : eventList) {
e. start О; // Перезапуск каждый раз addEvent(e);
}
startO; // Возвращаем это событие Event addEvent(this);
}
public String toStringO {
return "Перезапуск системы";
}
}
public static class Terminate extends Event {
public Terminatedong delayTime) { super(delayTime); }
public void actionO { System.exit(0); }
public String toStringO { return "Отключение"; }
}
} ///;-
Заметьте, что поля light, thermostat и ring принадлежат внешнему классу GreenhouseControls, и все же внутренние классы имеют возможность обращаться к ним, не используя особой записи и не запрашивая особых разрешений. Большинство методов action требует управления оборудованием оранжереи, что, скорее всего, привлечет в программу сторонние низкоуровневые вызовы.
В основном классы Event похожи друг на друга, однако классы Bell и Restart представляют собой особые случаи. Bell выдает звуковой сигнал и добавляет себя в список событий, чтобы звонок позднее сработал снова. Заметьте, что внутренние классы действуют почти как множественное наследование: классы Bell и Restart имеют доступ ко всем методам класса Event, а также ко всем методам внешнего класса GreenhouseControls.
Классу Restart передается массив объектов Event, которые он добавляет в контроллер. Так как Restart также является объектом Event, вы можете добавить этот объект в список событий в методе Restart.action, чтобы система регулярно перезапускалась.
Следующий класс настраивает систему, создавая объект GreenhouseControls и добавляя в него разнообразные типы объектов Event.
//: с08:GreenhouseControl1er.java // Настраивает и запускает систему управления. // {Args: 5000}
import innerclasses.control 1er.*:
public class GreenhouseController {
public static void main(String[] args) {
GreenhouseControls gc = new GreenhouseControls; // Вместо жесткого кодирования фиксированных данных // можно было бы считать информацию для настройки // из текстового файла: gc.addEvent(gc.new Bel 1 (900)): Event[] eventList = {
gc.new ThermostatNight(O), gc.new Light0n(200), gc.new LightOff(400), gc.new WaterOn(600), gc.new WaterOff(800), gc.new ThermostatDay(1400)
}:
gc.addEvent(gc.new Restart(2000, eventList)): if(args.length == 1) gc.addEvent(
new GreenHouseControls.Terminate( new Integer(args[0])));
gc.runO;
}
} * Output: Вам!
Термостат использует ночной режим
Свет включен
Свет выключен
Полив включен
Полив отключен
Термостат использует дневной режим Перезапуск системы Отключение ///:-
Класс инициализирует систему, включая в нее нужные события. Если передать программе параметр командной строки, она завершается по истечении заданного количества миллисекунд (используется при тестировании). Конечно, чтобы программа стала более гибкой, описания событий следовало бы не включать в программный код, а загружать из файла.
Этот пример поможет понять всю ценность механизма внутренних классов, особенно в случае с системами управления.
Наследование от внутренних классов
Так как конструктор внутреннего класса связывается со ссылкой на окружающий внешний объект, наследование от внутреннего класса получается чуть сложнее, чем обычное. Проблема состоит в том, что «скрытая» ссылка на объект объемлющего внешнего класса должна быть инициализирована, а в производном классе больше не существует объемлющего объекта по умолчанию. Для явного указания объемлющего внешнего объекта применяется специальный синтаксис:
//: innerclasses/Inheritlnner.java // Наследование от внутреннего класса.
class Withinner { class Inner {}
}
public class Inheritlnner extends Withlnner.Inner { //! InheritlnnerO {} // He компилируется InheritInner(WithInner wi) { wi.super;
}
public static void main(String[] args) { Withlnner wi = new WithlnnerO; Inheritlnner ii = new Inheritlnner(wi);
}
} ///:-
Здесь класс Inheritlnner расширяет только внутренний класс, а не внешний. Но когда дело доходит до создания конструктора, предлагаемый по умолчанию конструктор не подходит, и вы не можете просто передать ссылку на внешний объект. Необходимо включить в тело конструктора выражение