Приветствую всех изучающих Java!
На днях, ковыряя холодным осенним вечером Эккеля (Thinking in Java 4ed), окончательно во всем запутался. Читаю короткий абзац:
Реализация параметризованных интерфейсов
Класс не может реализовывать две разновидности одного параметризованного интерфейса — вследствие стирания они будут считаться одним и тем же интерфейсом. Пример конфликта такого рода:
interface Payable<T> {}
class Employee implements Payable<Employee> {}
class Hourly extends Employee implements Payable<Hourly> {}
Класс Hourly компилироваться не будет, потому что стирание сокращает Payable<Employee> и Payable<Hourly>
до Payable, а в приведенном примере это означало бы двукратную реализацию одного интерфейса. Интересная подробность: если удалить параметризованные аргументы из обоих упоминаний Payable, как это делает компилятор при стирании, программа откомпилируется.
Сразу оговорюсь — ситуация не является боевой, просто хочется нормально разобраться с теорией.
Разумеется заподозрил неладное, накидал по-быстрому исходник в Eclips`e… работает, собака, как и сказано.
Если начать чистить селёдку так сказать с хвоста, то вопросов к последнему утверждению просто никаких:
если удалить параметризованные аргументы из обоих упоминаний Payable, как это делает компилятор при стирании, программа откомпилируется
То есть будет:
class Employee implements Payable {}
class Hourly extends Employee implements Payable {}
OK, все нормально, интерфейс один и тот же, интерфейсы не наследуются, а значит в иерархии наследования можно сколько угодно реализовывать один и тот же интерфейс.
Чистим брюхо селёдки:
… стирание сокращает Payable<Employee>
и Payable<Hourly>
до Payable…
таак, немного пожёстче. Стирание не позволяет получать информацию о типе внутри параметризованного кода, компилятор генерит обычный НЕпараметризованый байт-код. Хорошо,
Payable<Employee> и Payable<Hourly>
стираются до ближайшего ограничения (а ограничений на параметр типа у нас нет —
interface Payable<T> {}
) или до «низкоуровневого» типа Payable.
Приближаемся к голове селедки:
Класс не может реализовывать две разновидности одного параметризованного интерфейса — вследствие стирания они будут считаться одним и тем же интерфейсом
ну, здОрово, компилятор просто сотрёт
Payable<Employee>
и
Payable<Hourly>
до Payable и всё. Очевидно, не всё. И в довершение совершенно непонятная фраза:
… в приведенном примере это означало бы двукратную реализацию одного интерфейса.
Вот как сие понимать?