JavaRush/Java блог/Архив info.javarush/Расширение/сужение ссылочных типов: разные источники - ра...
Core
35 уровень

Расширение/сужение ссылочных типов: разные источники - разная интерпретация

Статья из группы Архив info.javarush
участников
Добрый день. Есть подозрение на ошибку в лекциях JavaRush. Пусть есть класс Parent и унаследованный от него класс Child Пусть есть следующие строки кода: Parent parent = new Child; Child child = (Child) parent; Согласно лекции курса level 12, lesson 1 (1. Полиморфизм и переопределение), пункту 5) (Приведение типов.) первая строка - это сужение, а вторая расширение(в лекции Сow - родитель, Whale - наследник) Но ведь это неверно. Все с точностью наоборот. Смысл описанного понятен: в первой строке мы создали объект типа Child и ограничили его использование только методами, описанными в классе Parent. Но ведь это расширение поэтому такое приведение и происходит неявно. И в дополнительных материалах уровня 10 это было сказано:Your text to link...
Расширение означает переход от более конкретного типа к менее конкретному, т.е. переход от детей к родителям. В нашем примере преобразование от любого наследника ( Child, Child2 ) к родителю ( Parent ) есть расширение, переход к более общему типу. Подобно случаю с примитивными типами, этот переход производится самой JVM при необходимости и незаметен для разработчика, то есть не требует никаких дополнительных усилий, так как он всегда проходит успешно: всегда можно обращаться к объекту, порожденному от наследника, по типу его родителя. Parent p1=new Child(); Parent p2=new Child2(); В обеих строках переменным типа Parent присваивается значение другого типа, а значит, происходит преобразование. Поскольку это расширение, оно производится автоматически и всегда успешно.
Вторая строка моего примера, напротив, согласно этим же доп. материалам является сужением что требует явного указания типа в скобках. А в лекции она интерпретируется как расширение, что наверное неправильно Поясните, пожалуйста. Не хочу иметь двойное противоречивое представление о приведении типов. Ниже представлен фрагмент лекции фрагмент лекции Были еще подозрения на ошибки в лекциях (предыдущих) Куда об этом писать? В FAQ'е не нашел.
Комментарии (8)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Vitaly Khan Java Developer в Onollo Master
21 ноября 2018, 09:06
я тоже долго ломал голову, как правильно. тут действительно с какой стороны посмотреть.... субъективное восприятие понятий расширение и сужение. пожалуй, лучше всего принять за истину терминологию Оракл: https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.5 тогда получается Parent parent = new Child(); - это расширение / апкастинг - всегда безопасная операция Child child = (Child) parent; - это сужение / даункастинг - операция требует осторожности.
Nikita Zayakin
Уровень 20
22 октября 2018, 14:43
Можно для объектов, или иначе переменных ссылочного типа, рассмотреть терминологию восходящее и нисходящее преобразование, как например продемонстрированно тут. Это уменьшит путаницу по поводу Расширения, Сужения.
Fry
Уровень 41
29 марта 2016, 10:09
а что значит слово extends в java?
Core
Уровень 35
29 марта 2016, 10:32
Я так понял, это ключевое слово, применяемое при наследовании одного класса от другого. lev11.lesson5: здесь об этом говорится.
Например:
class Cat extends Pet{}

класс Cat унаследован от класса Pet
Мне не понятно, почему одни и те же приведения в разных источниках интерпретируются по-разному(противоположно).
Fry
Уровень 41
29 марта 2016, 11:18
ну, в переводе расширять.
Fry
Уровень 41
29 марта 2016, 11:18
Это просто как смотреть по цепочке иерархий классов. С верху в низ, или наоборот, с низу вверх.
Adelaida
Уровень 34
29 марта 2016, 15:46
мне стало понятней когда слово Расширение понимать как увеличение возможностей — ведь экземпляру становятся доступные методы не только класса родителя, а и потомка.
Например, есть 2 метода у Pet (спать и есть), а уже Cat расширяя добавил еще 1 метод (мяукать).
Теперь экземпляр Cat имеет 2 + 1 методов.
Core
Уровень 35
29 марта 2016, 16:36
Ну это понятно. Речь не о логике, речь о терминологии. Они иногда расходятся.
Посмтрите на принтскрин выше. Whale — наследник, Cow — родитель.

Cow cow = new Whale();

Я всегда это считал расширением. И вот здесь тоже об этом говорится: Your text to link... Не смотря на то, что по сути происхордит ограничение: теперь у объекта Whale можно вызвать только те методы, которые описаны в классе-родителе Сow, всё же это расширение типа судя по источнику из ссылки:
Есть расширяющее и сужающее приведение.
Мы видим, что класс Cat является наследником класса Pet. Pet, в свою очередь, наследник класса Animal.
Когда мы напишем:
Animal animalCat = new Cat();
Animal animalDog = new YorkshireTerrier();

Это расширяющее приведение (или неявное). Мы расширили ссылки animalCat и animalDog. Они ссылаются на объекты Cat и Dog. При таком приведении мы не можем через ссылку animalCat/animalDog вызвать методы, которые есть в Cat/Dog, но которых нету в Animal.
О том, что это расширение свидетельствует также тот факт, что оно происходит неявно.
А в лекции (см. принсткрин лекции из топика)это интерпретируется как сужение.