Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

Класс Filter содержит те же интерфейсные элементы, что и Processor, но, поскольку он не является производным от Processor (создатель класса Filter и не подозревал, что вы захотите использовать его как Processor), он не может использоваться с методом Apply.process, хотя это выглядело бы вполне естественно. Логическая привязка между Apply.process и Processor оказывается более сильной, чем реально необходимо, и это обстоятельство препятствует повторному использованию кода Apply.process. Также обратите внимание, что входные и выходные данные относятся к типу Waveform.

Но, если преобразовать класс Processor в интерфейс, ограничения ослабляются и появляется возможность повторного использования Apply.process. Обновленные версии Processor и Apply выглядят так:

//: interfaces/interfaceprocessor/Processor.java package interfaces interfaceprocessor;

public interface Processor { String nameO;

Object process(Object input), } ///-

//. interfaces/interfaceprocessor/Apply.java package i nterfaces.i nterfaceprocessor, import static net mindview.util.Print.*:

public class Apply {

public static void process(Processor p. Object s) { print ("Using Processor " + p.nameO): print(p.process(s)):

}

} ///:-

В первом варианте повторного использования кода клиентские программисты пишут свои классы с поддержкой интерфейса:

//: interfaces/interfaceprocessor/StringProcessor.java package i nterfaces.i nterfaceprocessor; import java.util.*;

public abstract class StringProcessor implements Processor! public String nameO {

return getClassO getSimpleNameO;

}

public abstract String process(Object input); public static String s =

"If she weighs the same as a duck, she's made of wood"; public static void main(String[] args) { Apply, process (new UpcaseO, s); Apply, process (new DowncaseO, s); Apply, process (new SplitterO. s);

class Upcase extends StringProcessor {

public String process(Object input) { II Ковариантный возвращаемый тип return ((String)input) .toUpperCaseO;

class Downcase extends StringProcessor { public String process(Object input) {

return ((String)input).toLowerCase;

class Splitter extends StringProcessor {

public String process(Object input) {

return Arrays.toString(((String)input).split(" ")).

}

} /* Output

Используем Processor Upcase

IF SHE WEIGHS THE SAME AS A DUCK, SHE'S MADE OF WOOD Используем Processor Downcase if she weighs the same as a duck, she's made of wood Используем Processor Splitter

[If. she. weighs, the. same. as. a. duck., she's, made. of. wood] *///:-

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

//: interfaces/interfaceprocessor/FilterProcessor java package interfaces interfaceprocessor, import interfaces.filters.*;

class FilterAdapter implements Processor { Filter filter.

public FilterAdapter(Filter filter) { this.filter = filter.

}

public String nameO { return filter.nameO; } public Waveform process(Object input) {

return filter.process((Waveform)input).

}

}

public class FilterProcessor {

public static void main(String[] args) { Waveform w = new Waveform; -

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

Так как интерфейс по определению не имеет реализации (то есть не обладает памятью для хранения данных), нет ничего, что могло бы помешать совмещению нескольких интерфейсов. Это очень полезная возможность, так как в некоторых ситуациях требуется выразить утверждение: «Икс является и А, и Б, и В одновременно». В С++ подобное совмещение интерфейсов нескольких классов называется множественным наследованием, и оно имеет ряд очень неприятных аспектов, поскольку каждый класс может иметь свою реализацию. В Java можно добиться аналогичного эффекта, но, поскольку реализацией обладает всего один класс, проблемы, возникающие при совмещении нескольких интерфейсов в С++, в Java принципиально невозможны:

При наследовании базовый класс вовсе не обязан быть абстрактным или «реальным» (без абстрактных методов). Если наследование действительно осуществляется не от интерфейса, то среди прямых «предков» класс может быть только один — все остальные должны быть интерфейсами. Имена интерфейсов перечисляются вслед за ключевым словом implements и разделяются запятыми. Интерфейсов может быть сколько угодно, причем к ним можно проводить восходящее преобразование. Следующий пример показывает, как создать новый класс на основе реального класса и нескольких интерфейсов:

Поделиться:
Популярные книги

Вечный. Книга VI

Рокотов Алексей
6. Вечный
Фантастика:
рпг
фэнтези
5.00
рейтинг книги
Вечный. Книга VI

Ваше Сиятельство 2

Моури Эрли
2. Ваше Сиятельство
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Ваше Сиятельство 2

Заточи свой клинок и Вперед!

Шиленко Сергей
1. Заточи свой клинок, и Вперед!
Фантастика:
юмористическая фантастика
рпг
попаданцы
5.00
рейтинг книги
Заточи свой клинок и Вперед!

Барон ломает правила

Ренгач Евгений
11. Закон сильного
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Барон ломает правила

Идеальный мир для Лекаря 3

Сапфир Олег
3. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 3

Законы Рода. Том 8

Мельник Андрей
8. Граф Берестьев
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Законы Рода. Том 8

Динка

Осеева Валентина Александровна
Детские:
детская проза
3.89
рейтинг книги
Динка

Хозяин Теней 5

Петров Максим Николаевич
5. Безбожник
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Хозяин Теней 5

Как я строил магическую империю 2

Зубов Константин
2. Как я строил магическую империю
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Как я строил магическую империю 2

Изгой Проклятого Клана. Том 3

Пламенев Владимир
3. Изгой
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Изгой Проклятого Клана. Том 3

Моя Академия

Листратов Валерий
1. Академка
Фантастика:
попаданцы
сказочная фантастика
фэнтези
4.50
рейтинг книги
Моя Академия

Иной. Том 5. Адская работа

Amazerak
5. Иной в голове
Фантастика:
боевая фантастика
городское фэнтези
технофэнтези
рпг
5.00
рейтинг книги
Иной. Том 5. Адская работа

Крепость над бездной

Лисина Александра
4. Гибрид
Фантастика:
боевая фантастика
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Крепость над бездной

Артефактор. Шаг в неизвестность

Седых Александр Иванович
1. Артефактор
Фантастика:
фэнтези
боевая фантастика
попаданцы
6.12
рейтинг книги
Артефактор. Шаг в неизвестность