Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137

Ограничение шаблона снизу

21.08.2015, 10:39. Показов 2828. Ответов 13
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Разбираю пример по учебнику, там говорится, что я могу ограничить шаблон снизу вот так: <? super подклассы>
Пробую в Eclipse-не получается вот что:
Есть метод
Java
1
2
3
4
5
6
7
8
9
static void showAll2(Coords<? super FourD> c) {
        System.out.println("X Y Z Coordinates: ");
        for (int i=0; i<c.coords.length; i++)
            System.out.println(c.coords[i].x + " "
                             + c.coords[i].y + " " 
                             + c.coords[i].z + " "
                            );
        System.out.println();       
    }
Класс TwoD привожу здесь:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Двухмерные координаты
public class TwoD {
    int x,y;
    
    TwoD(int a, int b) {
        x=a;
        y=b;
    }
}
 
//Трехмерные координаты
class ThreeD extends TwoD{
    int z;
    
    ThreeD(int a, int b, int c){
        super(a,b);
        z=c;
    }
}
 
//Четырехмерные координаты
class FourD extends ThreeD{
    int t;
    
    FourD(int a, int b, int c, int d) {
        super(a,b,c);
        t=d;
    }
}
По идее, так как метод showAll2 ограничен снизу, то он должен применяться и для типов ThreeD и TwoD. Но почему то Eclipse подчеркивает красным в этом методе c.coords[i].z, как будто ему неизвестно Z. Если же я ограничиваю шаблон снизу, то все прекрасно работает, например, метод, показанный ниже, прекрасно работает с типами ThreeD и FourD, а с типом TwoD нет, так как он ограничен сверху типом ThreeD:
Java
1
2
3
4
5
6
7
8
static void showXYZ(Coords<? extends ThreeD> c) {
        System.out.println("X Y Z Coordinates: ");
        for (int i=0; i<c.coords.length; i++)
            System.out.println(c.coords[i].x + " "
                             + c.coords[i].y + " " 
                             + c.coords[i].z);
        System.out.println();       
    }
и тут Eclipse ничего не подчеркивает. В чем тут может быть дело? Спасибо заранее!
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.08.2015, 10:39
Ответы с готовыми решениями:

Ограничение конкретизации шаблона
Есть виртуальный класс drawerShape и шаблонный класс Table. Необходимо реализовать шаблон так, чтобы Table можно было конкретизировать...

ListBox, ограничение списка элементов с помощью шаблона
ListBox , который с помощью шаблона может ограничивать список элементов. Например,если задать шаблон &quot;a?bc*&quot;, в списке...

Для использование шаблона переменной требуется список аргументов шаблона
Здравствуйте! Не могу понять в чём проблема. //ALL2.cpp #include &quot;pch.h&quot; #include &lt;iostream&gt; #include &lt;Windows.h&gt; ...

13
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
21.08.2015, 12:44
Цитата Сообщение от danek130995 Посмотреть сообщение
Разбираю пример по учебнику, там говорится, что я могу ограничить шаблон снизу вот так: <? super подклассы>
Выражение <? super FourD> означает, что годится любой предок вплодь до класса FourD.
Поэтому тут выбирается наименьший общий предок до FourD, которым является Object.
Классы-потомки FourD не подходят.

Выражение <? extends ThreeD> означает, что годится любой потомок (расширение) начиная с класса ThreeD.
Поэтому тут выбирается наименьший общий предок, которым является ThreeD.
Классы-предки ThreeD не подходят.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
21.08.2015, 14:02  [ТС]
EVP, это всё понятно, только
Цитата Сообщение от EVP Посмотреть сообщение
годится любой предок вплодь до класса FourD.
по учебнику написано, что это не включающее выражение, то есть класс FourD сам не включается. Вопрос же мой в том, почему метод showAll2 не видит своего предка ThreeD(именно там есть поле z)
0
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
21.08.2015, 15:00
Цитата Сообщение от danek130995 Посмотреть сообщение
по учебнику написано, что это не включающее выражение, то есть класс FourD сам не включается.
Переформулирую:
Подстановка <? super FourD> говорит, что можно подставить любого предка.
Элементы контейнера могут быть любым предком.
Наименьшим безопасным предком любых элементов такой подстановки в контейнере будет Object.
При такой подстановке, лишь класс FourD и его потомки могут быть безопасно присвоены контейнеру с любым неизвестным предком.

Поэтому для контейнера с подстановкой <? super FourD> тип элемента контейнера будет Object,
а присваивать элементу контейнера можно объекты класса FourD и любого потомка.

Цитата Сообщение от danek130995 Посмотреть сообщение
Вопрос же мой в том, почему метод showAll2 не видит своего предка ThreeD(именно там есть поле z)
Потому что
Java
1
showAll2(Coords<? super FourD> c)
это фактически интерпретируется как
Java
1
showAll2(Coords<Object> c)
с ограничением присваивания ему объектов класса FourD и его потомков.
А у класса Object нет поля z.
2
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
22.08.2015, 16:52  [ТС]
EVP, а почему предка FourD- ThreeD нельзя присвоить? Только Object что ли можно? Странно как-то. Смысл тогда этого?
0
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
22.08.2015, 19:45
Цитата Сообщение от danek130995 Посмотреть сообщение
а почему предка FourD- ThreeD нельзя присвоить? Только Object что ли можно?
Для твоего случая будет иерархия классов:
Object
TwoD
ThreeD
FourD.

При определении Coords<? super FourD> ты можешь подставить контейнеры:
Coords<Object>
Coords<TwoD>
Coords<ThreeD>
Coords<FourD>.

Для таких типов контейнеров безопасным приведением при присваивании его элементам будут только элементы типа FourD и его потомков.
Например, присваивание элементов типа ThreeD контейнеру типа Coords<FourD> (такая подстановка возможна) будет невозможно без приведения.
Поскольку приведение ThreeD к FourD является нисходящим по иерархии и потому небезопасно.
Присваивание элементов типа Object также гарантированно небезопасно.
Цитата Сообщение от danek130995 Посмотреть сообщение
Странно как-то. Смысл тогда этого?
Смысл только в ограничении на принимаемый контейнер и на возможные безопасные действия с его элементами при любом разрешённом контейнере.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
22.08.2015, 21:03  [ТС]
EVP,возможно, я не совсем понимаю, что вы имеете ввиду, или может я чего-то не знаю..Мне остается непонятным:
Цитата Сообщение от EVP Посмотреть сообщение
Для твоего случая будет иерархия классов:
Object
TwoD
ThreeD
FourD.
Если она будет для моего случая, почему тогда метод showAll2 не видит поле z класса ThreeD? Я не пойму, почему не соблюдается это правило: ThreeD является предком FourD, значит он должен быть виден этому методу, так как указано:Coords<? super FourD>, как должен быть виден и TwoD и Object.
0
 Аватар для ne2win
206 / 206 / 71
Регистрация: 25.02.2014
Сообщений: 569
22.08.2015, 21:25
danek130995, Coords<? super FourD> с = new Coords<Object>() - например, допустимая конструкция? Подумайте. И вопросы должны пропасть
1
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
22.08.2015, 22:34
Лучший ответ Сообщение было отмечено danek130995 как решение

Решение

Цитата Сообщение от danek130995 Посмотреть сообщение
почему тогда метод showAll2 не видит поле z класса ThreeD? Я не пойму, почему не соблюдается это правило: ThreeD является предком FourD, значит он должен быть виден этому методу, так как указано:Coords<? super FourD>, как должен быть виден и TwoD и Object.
Просто смотри на типы, которые можно подставить в подстановку и
определи возможность безопасного изменения контейнера для всех возможных подстановок.

Попробую обобщить:

Тип Coords<? super FourD> должен работать для любого супертипа,
поэтому он для компилятора схлопывается до минимального типа,
которым является тип Coords<Object> (это корень иерархии).
Поэтому showAll2 не видит вообще никакие поля твоих классов,
а не только поле z класса ThreeD, т.к для неё тип элементов Object.

Тут
минимальный тип подстановки Coords<Object>.
максимальный тип подстановки ограничен типом Coords<FourD>.
Максимальный тип важен для определения возможности присваивания элементам.

Поэтому
определение Coords<? super FourD> схлопнется до минимального типа Coords<Object>.
Элементам контейнера типа Coords<? super FourD> можно присваивать типы FourD и его наследники,
т.к. такое присваивание будет гарантированно безопасным для максимального типа элементов подстановки (тип FourD).
Т.е. c.coords[i] = new FourD(); вполне легален (т.к. максимально возможный тип подстановки Coords<FourD>),
но тип c.coords[i] будет Object (это минимальный тип элементов подстановки).

Если ты хочешь хочешь работать с классом FourD и его потомками,
то требуется ограничение Coords<? extends FourD>.
Т.к. в этом случае любые подстановки будут расширять тип FourD.
Т.е. тип c.coords[i] будет FourD для компилятора.

Тут
минимальный тип подстановки Coords<FourD>.
максимальный тип подстановки не ограничен.

Поэтому
определение Coords<? extends FourD> схлопнется до минимального типа Coords<FourD>
без возможности безопасного присвоения вообще, т.к. ограничения по максимальному типу подстановки нет.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
23.08.2015, 09:53  [ТС]
Kochmarik, EVP, У меня класс объявлен вот так: public class Coords<T extends TwoD>{}
И конструкция Coords<? super FourD> с = new Coords<Object>() не допустима ,
EVP, я все понял, огромное спасибо! Проверьте меня: Схлопываться в первом случае будет не до Object, так у меня класс, в котором объявлены эти методы, public class Coords<T extends TwoD>. Так что поля класса x,y видимы будут, а вот поле z нет, так как ThreeD-наследник класса TwoD, а родителям не видны поля наследников, а вот наоборот-поля суперкласса видны подклассам-это верно. Просто у меня че то вылетело это из головы, вот поэтому я и не понимал, почему поле z не видно.
P.S. под контейнером вы имеете ввиду объект класса? Просто я не встречал слово контейнер

Добавлено через 10 минут
EVP, сейчас попробовал сделать следующее:
Java
1
2
3
Object obj;
Coords<? super FourD> cd= new Coords<ThreeD>(thd);
cd=obj;
На 3-ю строчку компилятор ругается, странно ведь-тип <? super FourD> должен был схлопнуться до Object, почему я не могу присвоить объект типа Object ему?
0
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
23.08.2015, 12:34
Лучший ответ Сообщение было отмечено danek130995 как решение

Решение

Цитата Сообщение от danek130995 Посмотреть сообщение
Проверьте меня: Схлопываться в первом случае будет не до Object, так у меня класс, в котором объявлены эти методы, public class Coords<T extends TwoD>. Так что поля класса x,y видимы будут, а вот поле z нет, так как ThreeD-наследник класса TwoD, а родителям не видны поля наследников, а вот наоборот-поля суперкласса видны подклассам-это верно.
Верно.
Цитата Сообщение от danek130995 Посмотреть сообщение
P.S. под контейнером вы имеете ввиду объект класса? Просто я не встречал слово контейнер
Контейнер - это сущность, которая нужна для хранения каких-либо других объектов некоторого типа.
Стандартными контейнерами, например, являются: List<T>,Map<K,V>,Set<T> и другие.
Твой шаблон класса Coords<T> - тоже контейнер.

Цитата Сообщение от danek130995 Посмотреть сообщение
На 3-ю строчку компилятор ругается, странно ведь-тип <? super FourD> должен был схлопнуться до Object, почему я не могу присвоить объект типа Object ему?
Подстановка <? super FourD> действительно схлопывается до <Object> с ограничением присваивания типа FourD и его потомков.
Но подстановка ведь определяется для шаблона, а не сама по себе.
Поэтому тип Coords<? super FourD> схлопнется до Coords<Object>(с ограничениями на присваивание), предок которого Object.
Поэтому тут ты опять пытаешься сделать нисходящее приведение, на что компилятор ругается.
Но можно сделать такое:
Java
1
Coords<? super FourD> coords = new Coords<Object>();
и это безопасно.
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
23.08.2015, 13:42  [ТС]
EVP, ааа, я понял-так как предок Coords<Object> опять же-Object, то я пытался сделать нисходящее присваивание(Coords<Object> является наследником Object), и получил ошибку. Я еще помню, что переменная подкласса не может ссылаться на объект суперкласса, а вот наоборот-может. Спасибо огромное, выручили!

Добавлено через 9 минут
EVP, получается в книге ошибка? Там сказано, что:
<? super подклассы>-В этом случае допустимыми аргументами могут быть только классы, которые являются суперклассами для подклассы. Это исключающая конструкция, поскольку она не включает класс подклассы
. Но я смог присваивать и FourD включительно, а также смогу, как вы говорите, и его наследников
0
510 / 272 / 60
Регистрация: 14.12.2010
Сообщений: 548
23.08.2015, 14:59
Цитата Сообщение от danek130995 Посмотреть сообщение
получается в книге ошибка?
Это наверно особенности перевода. Хотели сказать:
<? super подклассы>-В этом случае допустимыми аргументами могут быть только классы, которые являются суперклассами для подклассы и классом подклассы. Это исключающая конструкция, поскольку она не включает подклассы класса подклассы.
Переводчик небось тыщу страниц пытался переварить, а он не железный как компилятор
1
 Аватар для danek130995
33 / 33 / 3
Регистрация: 25.05.2014
Сообщений: 1,137
23.08.2015, 16:17  [ТС]
EVP, понятно) Спасибо
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.08.2015, 16:17
Помогаю со студенческими работами здесь

Gtest, доступ к элементам базового класса-шаблона без указания параметров шаблона. баг или фича?
Всем привет. Продолжаю экспертизу gtest/gmock. Количество ошибок и багов зашкаливает. Ничего удивительного, учитывая то, ...

Определение метода-шаблона за пределами шаблона класса
День добрый! Разбираюсь в шаблонах, решил копнуть поглубже. Вот пример: template &lt;typename T1&gt; class K // шаблон класса { ...

Редактирование шаблона сайта и шаблона письма
Помогите найти , где и как ? Т.е. уже 3 дня роюсь и не в состоянии найти где убить пару кнопок и поменять логотип и где редактировать...

Как создать ограничение? Надо создать ограничение ввода букв, а то программа виснет!
var a:integer; begin repeat; writeln ('Введите число не равное еденице'); readln (a);

Обтекание снизу
Вот есть у меня вот такой код: &lt;hr class=&quot;line line_2&quot;&gt; &lt;body onload=&quot;digitalWatch()&quot;&gt; &lt;p id=&quot;digital_watch&quot;...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru