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

// Работа метода не зависит от фактического типа объекта, // поэтому типы, добавленные в систему, будут работать правильно public static void tune(Instrument i) { // ...

i.play(Note.MIDDLE_C),

}

public static void tuneAll(Instrument!!] e) { for(Instrument i : e) tune(i);

}

public static void main(String[] args) {

// Восходящее преобразование при добавлении в массив Instrument!!] orchestra = { new WindO. new PercussionO. new StringedO, new BrassO, new WoodwindО

}:

tuneAll(orchestra),

}

} /* Output. Wind.pi ayО MIDDLE_C Percussion.playO MIDDLE_C Stringed.pi ayО MIDDLE_C Brass.playO MIDDLE_C Woodwind pi ayО MIDDLE_C *///:-

Новый метод what() возвращает строку (String) с информацией о классе, а метод adjust() предназначен для настройки инструментов.

В методе main() сохранение любого объекта в массиве orchestra автоматически приводит к выполнению восходящего преобразования к типу Instrument.

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

Проблема: «переопределение» закрытых методов

Перед вами одна из ошибок, совершаемых по наивности:

//: polymorph!sm/PrivateOverride.java

// Попытка переопределения приватного метода

package polymorphism;

import static net.mindview.util.Print.*;

public class PrivateOverride {

private void f() { printCprivate f(D; } public static void main(String[] args) {

Pri vateOverride po = new DerivedO; po.fO:

}

class Derived extends PrivateOverride {

public void f() { print("public f()"). } } /* Output

private f() *///-

Вполне естественно было бы ожидать, что программа выведет сообщение public f(), но закрытый (private) метод автоматически является неизменным (final), а заодно и скрытым от производного класса. Так что метод f() класса Derived в нашем случае является полностью новым — он даже не был перегружен, так как метод f() базового класса классу Derived недоступен.

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

Конструкторы и полиморфизм

Конструкторы отличаются от обычных методов, и эти отличия проявляются и при использовании полиморфизма. Хотя конструкторы сами по себе не полиморфны (фактически они представляют собой статические методы, только ключевое слово static опущено), вы должны хорошо понимать, как работают конструкторы в сложных полиморфных иерархиях. Такое понимание в дальнейшем поможет избежать некоторых затруднительных ситуаций.

Порядок вызова конструкторов

Порядок вызова конструкторов коротко обсуждался в главах 5 и 7, но в то время мы еще не рассматривали полиморфизм.

Конструктор базового класса всегда вызывается в процессе конструирования производного класса. Вызов автоматически проходит вверх по цепочке наследования, так что в конечном итоге вызываются конструкторы всех базовых классов по всей цепочке наследования. Это очень важно, поскольку конструктору отводится особая роль — обеспечивать правильное построение объектов. Производный класс обычно имеет доступ только к своим членам, но не к членам базового класса (которые чаще всего объявляются со спецификатором private). Только конструктор базового класса обладает необходимыми знаниями и правами доступа, чтобы правильно инициализировать свои внутренние элементы. Именно поэтому компилятор настаивает на вызове конструктора для любой части производного класса. Он незаметно подставит конструктор по умолчанию, если вы явно не вызовете конструктор базового класса в теле конструктора производного класса. Если конструктора по умолчанию не существует, компилятор сообщит об этом. (Если у класса вообще нет пользовательских конструкторов, компилятор автоматически генерирует конструктор по умолчанию.)

Следующий пример показывает, как композиция, наследование и полиморфизм влияют на порядок конструирования:

// polymorphism/Sandwich.java

// Порядок вызова конструкторов.

package polymorphism,

import static net mindview.util.Print.*;

class Meal {

Meal О { printCMealO"). }

}

class Bread {

BreadO { printCBreadO"). }

}

class Cheese {

CheeseO { printC'CheeseO"). }

}

class Lettuce {

LettuceO { print("Lettuce()"); }

}

class Lunch extends Meal {

Lunch0 { printC'LunchO"). }

}

class PortableLunch extends Lunch {

PortableLunchO { printC'PortableLunchO");}

}

public class Sandwich extends PortableLunch { private Bread b = new BreadO, private Cheese с = new CheeseO, private Lettuce 1 = new LettuceO; public Sandwich0 { print("Sandwich()"); } public static void main(String[] args) { new SandwichO;

}

} /* Output: Meal О LunchO

PortableLunchO BreadO CheeseO LettuceO SandwichO *///:-

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

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

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

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

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

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

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

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

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