Apply process(new FilterAdapter(new LowPass(l.O)), w); Apply.process(new FilterAdapter(new HighPass(2.0)). w); Apply.process(
new FilterAdapter(new BandPass(3.0. 4 0)). w);
}
} /* Output.
Используем Processor LowPass Waveform 0
Используем Processor HighPass Waveform 0
Используем Processor BandPass
Waveform 0 *///.-
Конструктор FilterAdapter получает исходный интерфейс (Filter) и создает объект с требуемым интерфейсом Processor. Также обратите внимание на применение делегирования в классе FilterAdapter.
Отделение интерфейса от реализации позволяет применять интерфейс к разным реализациям, а следовательно, расширяет возможности повторного использования кода.
«Множественное наследование» в Java
Так как интерфейс по определению не имеет реализации (то есть не обладает памятью для хранения данных), нет ничего, что могло бы помешать совмещению нескольких интерфейсов. Это очень полезная возможность, так как в некоторых ситуациях требуется выразить утверждение: «Икс является
При наследовании базовый класс вовсе не обязан быть абстрактным или «реальным» (без абстрактных методов). Если наследование
//: interfaces/Adventure java
// Использование нескольких интерфейсов.
interface CanFight { void fightO,
}
interface CanSwim { void swimO,
}
interface CanFly { void fly().
}
class ActionCharacter {
public void fightO {}
}
class Hero extends ActionCharacter
implements CanFight, CanSwim, CanFly { public void swimO {}
public void fly() {}
}
public class Adventure {
public static void t(CanFight x) { x fightO; } public static void u(CanSwim x) { x swimO, } public static void v(CanFly x) { x fly(); } public static void w(ActionCharacter x) { x.fightO. } public static void main(String[] args) { Hero h = new HeroO;
t(h), // Используем объект в качестве типа CanFight u(h). // Используем объект в качестве типа CanSwim v(h). // Используем объект в качестве типа CanFly w(h), // Используем объект в качестве ActionCharacter
}
} ///-
Мы видим, что класс Него сочетает реальный класс ActionCharacter с интерфейсами CanFight, CanSwim и CanFly. При объединении реального класса с интерфейсами на первом месте должен стоять реальный класс, а за ним следуют интерфейсы (иначе компилятор выдаст ошибку).
Заметьте, что объявление метода fight() в интерфейсе CanFight совпадает с тем, что имеется в классе ActionCharacter, и поэтому в классе Него
Класс Adventure содержит четыре метода, которые принимают в качестве аргументов разнообразные интерфейсы и реальный класс. Созданный объект Него передается всем этим методам, а это значит, что выполняется восходящее преобразование объекта к каждому интерфейсу по очереди. Система интерфейсов Java спроектирована так, что она нормально работает без особых усилий со стороны программиста.
Помните, что главная причина введения в язык интерфейсов представлена в приведенном примере: это возможность выполнять восходящее преобразование к нескольким базовым типам. Вторая причина для использования интерфейсов совпадает с предназначением абстрактных классов: запретить програм-мисту-клиенту создание объектов этого класса.
Возникает естественный вопрос: что лучше — интерфейс или абстрактный класс? Если можно создать базовый класс без определений методов и переменных-членов, выбирайте именно интерфейс, а не абстрактный класс. Вообще говоря, если известно, что нечто будет использоваться как базовый класс, первым делом постарайтесь сделать это «нечто» интерфейсом.
Расширение интерфейса через наследование
Наследование позволяет легко добавить в интерфейс объявления новых методов, а также совместить несколько интерфейсов в одном. В обоих случаях получается новый интерфейс, как показано в следующем примере:
//• interfaces/HorrorShow java
// Расширение интерфейса с помощью наследования
interface Monster { void menace(),
}