2014-11-27 3 views
5

Мой друг нашел эту пикантную в Java API (https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html),Использование рекурсивных границ типа

Class Enum<E extends Enum<E>> 

и читая следующую статью https://docs.oracle.com/javase/tutorial/java/generics/genTypes.html я мог понять, что вышеупомянутая линия влечет за собой синтаксически, но из примеров учитывая, что я не мог определить прецедент для этого за пределами класса Enum (рассмотрел источник).

Я хотел бы узнать больше о возможных проблемах, когда вышеприведенное может представить решение.

ответ

4

Это, например, полезный для позволить подклассы использовать свой собственный тип

Представьте себе класс, как

class Node { 
    Node next; 
} 

, если продлить этот класс, вы застряли с Node.

class SpecialNode extends Node { 
    void foo() { 
     // euwww 
     SpecialNode nextNode = (SpecialNode) this.next; 
    } 
} 

Вы также не можете просто определить его как

class Node<T> { 
    T next; 
} 

потому, что позволило бы что-нибудь для T. Вы действительно хотите T, что extends Node или вы больше не можете использовать T как Node с точностью до Node без литья. Тем не менее, это работало бы на детские классы.

С помощью рекурсивных оценок как

class Node<T extends Node<T>> { 
    T next; 
} 

Вы ограничить T для себя или подклассов себя, который затем позволяет сделать

class SpecialNode extends Node<SpecialNode> { 
    void foo() { 
     SpecialNode nextNode = this.next; // type-safe! 
    } 
} 

Таким образом, как родитель и ребенок класс может получить доступ ко всему на их Уровень абстракции полностью типичен.

2

Обычно он полезен для определения некоторого поведения в суперклассе (например, в Enum), который зависит от информации о типе, относящейся к подтипу рассматриваемого класса (I actually asked a similar question a wee while ago).

+0

Я не думаю, что этот вопрос такой же, как ваш вопрос.(Это не имеет никакого отношения к литералам класса.) – Radiodef

+0

Да, я полагаю, я слишком сильно подпрыгнул. Тем не менее, он все еще передает информацию о подтипе суперклассу, хотя и только во время компиляции (например, для сигнатур метода). – errantlinguist

+0

P.S. Должен ли я удалить ответ, так как я признаю, что он неправильный или он должен остаться? - Я никогда не понял все это ... – errantlinguist

2

Эта идиома почти всегда означает 'E должен быть типом подкласса. Например, вы можете заметить, что Enum implements Comparable<E>.

Когда класс расширяется, вы получите что-то вроде:

//   E extends Enum<E> ┐ 
class AnEnum extends Enum<AnEnum> {...} 

Теперь AnEnum также Comparable<AnEnum> и getDeclaringClass возвращает Class<AnEnum>.

Я видел эту идиому, связанную с curiously recurring template pattern. Цель состоит в том, что суперкласс может ссылаться на подкласс в целом.

(В связи с тем, что подкласс Enum генерируется компилятором, я не думаю, что есть на самом деле причина Enum, в частности, необходимо объявлять этот путь. Он мог бы просто был Enum<E>.)

+0

Это правильный шаблон, а не тот, который в моем ответе +1 – errantlinguist

Смежные вопросы