1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/wizardforcel-thinking-in-java-zh

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
6.7 向上转换.md 8.4 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
Отправлено 11.03.2025 09:15 d56454c

6.7 Преобразование в родительский тип

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

Это представление не просто метафорическое объяснение наследования; оно непосредственно поддерживается языком программирования. В качестве примера рассмотрим базовый класс Instrument, который используется для представления музыкальных инструментов, и производный класс Wind. Поскольку наследование означает, что все методы базового класса также доступны в производном классе, любое сообщение, отправленное базовому классу, может быть отправлено и производному классу. Если класс Instrument имеет метод play(), то устройство типа Wind также будет иметь этот метод. Это означает, что мы можем уверенно говорить, что объект типа Wind является типом Instrument. Приведённый ниже пример демонстрирует, как компилятор обеспечивает поддержку этого концепта:

//: Wind.java
// Наследование и преобразование в родительский тип
import java.util.*;

class Instrument {
  public void play() {}
  static void tune(Instrument i) {
    // ...
    i.play();
  }
}
```// Объекты типа Wind являются инструментами,
// поскольку они имеют одинаковое API:
class Wind extends Instrument {
  public static void main(String[] args) {
    Wind flute = new Wind();
    Instrument.tune(flute); // Преобразование в родительский тип
  }
} ///:~Наиболее интересной частью этого примера является метод `tune()`, который принимает ссылку на объект типа `Instrument`. Однако в методе `main()` класса `Wind` метод `tune()` вызывается через передачу ему ссылки на объект типа `Wind`. Из-за строгой проверки типов в Java, это может показаться странным: почему метод, принимающий один тип, может принимать другой? Но важно понимать, что объект типа `Wind` также является объектом типа `Instrument`. Кроме того, для объекта типа `Instrument`, который не находится внутри класса `Wind`, нет методов, которые могут быть вызваны методом `tune()`. В методе `tune()` код применим ко всему, что происходит от `Instrument`. Здесь процесс преобразования ссылки типа `Wind` в ссылку типа `Instrument` называют "преобразованием в родительский тип".

## 6.7.1 Что такое "преобразование в родительский тип"?Почему этот термин был выбран, помимо исторических причин, связано и с тем, что традиционно диаграммы наследования рисуются так, чтобы корневой класс располагался сверху, а остальные классы расширялись вниз (хотя можно использовать любой подход для создания таких диаграмм). Поэтому диаграмма наследования для файла `Wind.java` выглядит следующим образом:

Поскольку конвертация направлена от производного класса к базовому классу, стрелка указывает вверх, поэтому её обычно называют "вверхуправлением" или `Upcasting`. Вверхуправление всегда безопасно, так как мы переходим от более специфичного типа к более общему типу. Другими словами, производный класс является суперсетом базового класса. Он может содержать больше методов, чем базовый класс, но он обязательно содержит все методы базового класса. Единственная проблема, которая может возникнуть при выполнении вверхуправления, заключается в потере доступа к некоторым методам, а не в получении новых методов. Это объясняет, почему компилятор позволяет выполнять вверхуправление без явной конвертации или других специальных меток.Также можно выполнить обратное управление, но это приведёт к сложностям, подробно рассмотренным в главе 11.

(1) Опять же о композиции и наследованииВ объектно-ориентированном программировании наиболее вероятным подходом к созданию и использованию кода является его упаковывание вместе с данными и методами в одном классе и использование объектов этого класса. Иногда требуется использовать технику "компоновки", чтобы создать новый класс с помощью существующих классов. Наследование  это самый редко используемый подход. Поэтому, хотя наследование получает большое внимание во время обучения OOP, это не значит, что следует применять его повсюду. Наоборот, следует относиться к нему с особым вниманием. Его следует рассматривать только тогда, когда вы уверены, что наследование будет самым эффективным способом среди всех возможных вариантов. Для того чтобы решить, стоит ли выбрать компоновку или наследование, самый простой способ  проверить, требуется ли вам осуществлять управление от нового класса к базовому классу. Если требуется управление, то нужна наследование. Но если нет необходимости в управлении, следует помнить о возможности злоупотребления наследованием. В следующей главе (полиморфизм) будут представлены случаи, где действительно требуется управление. Однако, если постоянно спрашивать себя "Нужно ли мне в действительности управление?", выбор между компоновкой и наследованием не должен вызывать больших трудностей.

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/wizardforcel-thinking-in-java-zh.git
git@api.gitlife.ru:oschina-mirror/wizardforcel-thinking-in-java-zh.git
oschina-mirror
wizardforcel-thinking-in-java-zh
wizardforcel-thinking-in-java-zh
master