Главная » Java » Наследование вложенных типов в составе внешних

0

Вложенные типы, будь то статические классы, интерфейсы или внутренние классы, передаются по наследству в производные классы точно так же, как и обычные поля. Объявление вложенного типа в производном классе перекрывает одноименный унаследованный тип. Фактический тип определяется типом используемой ссылки

Рассмотрим программную структуру, моделирующую устройства, которые могут быть подключены друг к другу с помощью различных портов. Device это абстрактный класс, описывающий некоторые характеристики поведения, присущие всем устройствам. Порты также обладают некоторыми общими чертами, которые определяются в соответствующем абстрактном классе Роrt. Поскольку порт является атрибутом устройства, класс Роrt объявлен как внутренний по отношению к классу Device. Конкретный класс устройства определяет состояние устройства и набор конкретных классов портов для него. Ссылки на объекты конкретных классов портов устройства инициализируются в процессе создания конкретного класса устройства.

abstract class Device {

 abstract class Port {

// …

}

// …

}

class Printer extends Device {

class SerialPort extends Port { / / …

}

Port serial = new SerialPort();

}

Конкретный класс устройства, в свою очередь, может быть расширен совместно с конкретным внутренним классом порта, с целью определения некоторых специальных характеристик:

class НighSpeedPrinter extends printer {

class SerialPort extends Printer.SerialPort { // …

}

}

Цель, в соответствии с которой класс НighSpeedPrinter.SerialPort переопределяет класс printer.SerialPort, состоит в том, чтобы поле serial получило ссылку на объект корректного типа. Но к классу Рrinter новый производный от SerialPort класс, определенный внутри НighSpeedPrinter, не имеет отношения, хотя и обладает прежним именем.

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

class printer extends Device {

class SerialPort extends Port {

// … }

Port serial = createSerialPort();

 protected Port createSerialPort() {

return new SerialPort();}

}

 

 

Теперь класс НighSpeedPrinter вправе объявить собственный специализированный внутренний класс и переопределить метод createSerialPort таким образом, чтобы тот позволял конструировать экземпляры нового класса. Сейчас мы понимаем, что определения внутренних типов перекрываются, но не переопределяются, и поэтому не следует искушать судьбу, используя прежнее имя внутреннего класса, поскольку сокрытие имен обычно не сулит ничего хорошего.

class НighSpeedPrinter extends Printer {

class EnhancedSerialPort extends SerialPort { / / …

}

protected Port createSerialPort() {

return new EnhancedSerialPort();

}

}

в Процессе конструирования объекта класса НighSpeedPrinter и выполнения инициализаторов класса printer вызывается переопределенная версия метода CreateSerialPort, которая возвращает экземпляр типа EnhancedSerialPort.

Это пример ситуации, когда метод производного класса вызывается еще до того, как объект этого класса полностью сконструирован, и поэтому она заслуживает самого пристально го внимания. Если, скажем, поле в EnhancedSerialPort инициализируется значением поля во внешнем коде НighSpeedPrinter, в момент конструирования объекта класса EnhancedSerialPort поля внешнего объекта все еще будут обладать исходными "нулевыми" значениями, предлагаемыми по умолчанию.

При другом подходе конструктор для НighSpeedPrinter мог бы просто присвоить полю serial ссылку на объект класса EnhancedSerialРоrt. Такая Мера, однако, привела бы к излишним затратам, связанным с конструированием объекта типа SerialРоrt, которые в общем случае оказались бы ощутимы и нежелательны (в нашем примере это могло бы означать выполнение ненужных операций по настройке аппаратного обеспечения).

 

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

  • Комментарии