Читаем Философия Java3 полностью

Как было показано в главе 7, с объектом можно работать с использованием как его собственного типа, так и его базового типа. Интерпретация ссылки на объект как ссылки на базовый тип называется восходящим преобразованием.

Также были представлены проблемы, возникающие при восходящем преобразовании и наглядно воплощенные в следующей программе с музыкальными инструментами. Поскольку мы будем проигрывать с их помощью объекты Note (нота), логично создать эти объекты в отдельном пакете:

II polymorphism/music/Musi с java

// Объекты Note для использования с Instrument

package polymorphism.music,

public enum Note {

MIDDLE_C. C_SHARP, B_FLAT, // И т.д } /// ~

Перечисления были представлены в главе 5. В следующем примере Wind является частным случаем инструмента (Instrument), поэтому класс Wind наследует от Instrument:

//• polymorphism/music/instrument java

package polymorphism.music,

import static net mindview.util.Print.*,

class Instrument {

public void play(Note n) {

print("Instrument.pi ay(Г);

}

}

III ~

//• polymorphism/music/Wind java package polymorphism.music;

// Объекты Wind также являются объектами Instrument, II поскольку имеют тот же интерфейс: public class Wind extends Instrument { // Переопределение метода интерфейса public void pi ay(Note n) {

System out pri ntl n( "Wind playO " + n),

}

} III-

II polymorphism/music/Music.java II Наследование и восходящее преобразование package polymorphism music,

public class Music {

public static void tune(Instrument i) { // ...

i.play(Note.MIDDLE_C),

}

public static void main(String[] args) {

Wind flute = new WindO

tune(flute). // Восходящее преобразование

}

} /* Output

Wind playO MIDDLE_C

*/// -

Метод Music.tune() получает ссылку на Instrument, но последняя также может указывать на объект любого класса, производного от Instrument. В методе main() ссылка на объект Wind передается методу tune() без явных преобразований. Это нормально; интерфейс класса Instrument должен существовать и в классе Wind, поскольку последний был унаследован'от Instrument. Восходящее преобразование от Wind к Instrument способно «сузить» этот интерфейс, но не сделает его «меньше», чем полный интерфейс класса Instrument.

Потеря типа объекта

Программа Music.java выглядит немного странно. Зачем умышленно игнорировать фактический тип объекта? Именно это мы наблюдаем при восходящем преобразовании, и казалось бы, программа стала яснее, если бы методу tune() передавалась ссылка на объект Wind. Но при этом мы сталкиваемся с очень важным обстоятельством: если поступить подобным образом, то потом придется писать новый метод tune() для каждого типа Instrument, присутствующего в системе. Предположим, что в систему были добавлены новые классы Stringed и Brass:

// polymorphi sm/musi c/Musi c2.java // Перегрузка вместо восходящего преобразования package polymorphism.music, import static net.mindview util Print *;

class Stringed extends Instrument {

public void play(Note n) {

pri nt ("Stri nged.pl ay() " + n):

}

}

class Brass extends Instrument {

public void play(Note n) {

printC'Brass playO " + n),

}

}

public class Music2 {

public static void tune(Wind i) { i.play(Note MIDDLE_C),

}

public static void tune(Stringed i) { i.play(Note MIDDLE'C);

}

public static void tune(Brass i) { i play(Note.MIDDLE_C);

}

public static void main(String[] args) {

Wind flute = new Wind(),

Stringed violin = new StnngedO.

Brass frenchHorn = new BrassO.

tune(flute), // Без восходящего преобразования

tune(violin);

tune(frenchHorn).

}

} /* Output

Wind playO MIDDLE_C

Stringed.pi ayО MIDDLE_C

Brass pi ayО MIDDLE_C *///-

Программа работает, но у нее есть огромный недостаток: для каждого нового Instrument приходится писать новый, зависящий от конкретного типа метод tune(). Объем программного кода увеличивается, а при добавлении нового метода (такого, как tune()) или нового типа инструмента придется выполнить немало дополнительной работы. А если учесть, что компилятор не выводит сообщений об ошибках, если вы забудете перегрузить один из ваших методов, весь процесс работы с типами станет совершенно неуправляемым.

Разве не лучше было бы написать единственный метод, в аргументе которого передается базовый класс, а не один из производных классов? Разве не удобнее было бы забыть о производных классах и написать обобщенный код для базового класса?

Именно это и позволяет делать полиморфизм. Однако большинство программистов с опытом работы на процедурных языках при работе с полиморфизмом испытывают некоторые затруднения.

Особенности

Сложности с программой Music.java обнаруживаются после ее запуска. Она выводит строку Wind.play(). Именно это и требуется, но не понятно, откуда берется такой результат. Взгляните на метод tune():

public static void tune(Instrument i) {

//

i play(Note.MIDDLE_C),

}

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных