5

Допутим у меня есть иреархия классов.
Во главе иерархии стоит класс А, за ним B, C и тд. Наследуются друг от друга.
Уместно ли будет делать такое?

A obj = new B();          //(Расширение)
B obj = new A();          //(Сужение)
1
  • Расширение - да, сужение - нет.
    – Nofate
    23 ноя 2012 в 7:36

2 ответа 2

18

Думайте по-другому. Расширение-сужение — слишком абстрактно.

Производный тип — это всегда более конкретный вариант базового. Пускай вместо базового типа будет «Рыба», а вместо производного — «Селёдка».

Тогда совершенно очевидно, что писать

Рыба р = new Селёдка();

можно: ваша р — рыба, например, селёдка, почему бы и нет.

Но писать наоборот:

Селёдка с = new Рыба();

нельзя: рыба ведь не обязательно селёдка, правда?

Можно использовать преобразование типов:

// у вас есть какая-то рыба
Рыба р;
// тут много кода
// а здесь вы точно знаете, что ваша рыба на самом деле селёдка
// тогда можно использовать приведение типов
Селёдка с = (Селёдка)р;
// но если вы ошиблись, и в прошлой строке рыба была на самом деле
// акулой, вы получите exception

Как проверить, рыба ли ваша селёдка? Этого не нужно: Селёдка наследник Рыбы, то есть каждая Селёдка обязательно Рыба.

Как проверить, селёдка ли ваша рыба? Очень просто:

Рыба р;
// много кода
if (р instanceof Селёдка)
{
    // о, оказывается, наша рыба -- селёдка!
    Селёдка с = (Селёдка)р; // здесь исключения не будет
}
5
  • @VladD Я лучше сдамся. А то лезть в определения... Лениво. По моему убеждению (может не совпадать с чем угодно) строгая статическая типизация не требует проверки типов во время выполнения. Возможно с точки зрения науки я не прав. Вполне допускаю. Да, и спасибо за демонстрацию того, что java-compiler кушает идентификаторы из русских букв. Не знал.
    – alexlz
    24 ноя 2012 в 15:28
  • @alexlz: Я вовсе не хотел "победить" вас, просто мне самому такие вопросы интересны. И интересно ваше мнение по поводу строгой типизации. Не сочтите уточняющие вопросы за придирки. Как мне кажется, единого понимания строгой типизации не существует. Вот, например, мнение Эрика Липперта, одного из архитекторов C#: blogs.msdn.com/b/ericlippert/archive/2012/10/15/…
    – VladD
    24 ноя 2012 в 16:22
  • 2
    @alexlz: Возвращаясь к теме дискуссии, мне кажется, что в хорошо написанной программе процент даун-кастов, instanceof, dynamic_cast<> и тому подобного должен быть очень мал как по объёму кода, так и по количеству выполнений за время пробега программы. Злоупотребление такими конструкциями обычно означает неправильную архитектуру проекта.
    – VladD
    24 ноя 2012 в 16:27
  • @VladD извинения излишни, меня моя неграмотность не сильно беспокоит. Да и тема-то непростая. А насчёт ап-кастов/даун-кастов, так библиотеки контейнерных классов без них как будут работать? (В C++ это ушло в тень после введения шаблов-templates, а когда-то тоже цвело пышным цветом).
    – alexlz
    24 ноя 2012 в 16:38
  • @alexlz: с шаблонами и правда даун-касты не нужны. В Джаве генерики реализованы так, что в рантайме контейнеры содержат просто ссылки на Object, даун-касты вставляются компилятором, отчего производительность не выигрывает. В C#, в отличие от Джавы, генерики сделаны правильно, и содержат настоящие ссылки на объекты правильного типа, так что даун-касты не нужны. То же и в C++, поскольку каждая инстанциация шаблона компилируется отдельно. То есть, для контейнеров даун-касты не нужны, если язык это позволяет. Джава в этом смысле проигрывает как Шарпу, так и C++, в ней без даун-кастов не обойтись.
    – VladD
    24 ноя 2012 в 16:53
11

Нельзя наследнику присвоить предка. Только если Вы предку (указателю на объект-предок) заранее присвоили указатель на объект-потомок, то обратное присваивание выполнять можно.

UPD

    class A {
        ...
    }

    class B extends A {
       ... 
    }

    ...
    B b = new B();
    A a = b;       // можно
    B c = (B) a;   // можно

    A a1 = new A();
    B b1 = a1;      // нельзя
3
  • лучше б вы на примере кода показали что можно а что нет, так понятнее будет
    – jmu
    23 ноя 2012 в 16:42
  • сужение низя 24 ноя 2012 в 9:44
  • @jmu дополнил ответ
    – alexlz
    24 ноя 2012 в 10:17

Всё ещё ищете ответ? Посмотрите другие вопросы с метками или задайте свой вопрос.