2015-10-17 2 views
2

У меня есть интерфейс, какПараметр дополнительного типа позволяет избежать ошибочной ошибки переопределения?

public interface AnInterface { 
    Consumer<Object> getConsumer(); 
} 

И класс реализации как

public class AClass implements AnInterface { 
    @Override 
    public Consumer<String> getConsumer() { 
     return System.out::println; 
    } 
} 

это (правильно) не компилируется, поскольку Consumer<String> не распространяется Consumer<Object>.

Однако, если я изменить интерфейс, чтобы иметь дополнительный неиспользуемый параметр типа на getConsumer, ошибка исчезнет, ​​и он отлично компилируется:

<T> Consumer<Object> getConsumer(); 

Что здесь происходит ?!

Это происходит с javac в JDK 1.8 u20 и компилятором Eclipse в Luna.

+0

Спасибо за очень хороший вопрос. –

+0

странно, что он не компилируется в первую очередь, вы должны иметь возможность переопределить с более конкретным типом в обратном направлении, который расширяет (присваивается) исходный тип http://stackoverflow.com/questions/14694852/can-overridden- методы-differ-in-return-type – Hurda

+0

@Hurda, это не то же самое. –

ответ

3

Причина код компилируется, когда вы добавляете параметр типа <T>, является то, что в этом случае вы перекрывая сыройgetConsumer() метод , т.е. вы не переопределения параметра типа (<T>), но вы просто игнорируя это.

Стоит отметить, что при расширении сырых классов или верховные сырых методов, всей общей информация просто игнорируются, что означает, что в этом случае компилятор не будет проверять, если параметр типа методы замещения (<String>) совместим с параметром типа абстрактного метода (<Object>).

Если бы вы держали метод, как общий, он будет выглядеть так:

@Override 
public <T> Consumer<String> getConsumer() { 
    ... 
} 

, а затем компилятор исправит поднять ошибку во время компиляции.

+0

Я думал, что что-то подобное может произойти, но я был смущен, так как это не ошибка, которую мой класс не делает Действительно ли реализовать интерфейс? У вас есть ссылка на дополнительную информацию о том, как это работает? – takteek

+0

Подождите, как это сыро? Это, по-видимому, конкретно связано. – Makoto

+0

@Makoto, метод является общим, если он определяет параметр типа (без учета того, что тип возврата является общим или нет). Когда абстрактный метод интерфейса определяет параметр типа, но метод реализации не заботится об этом (т. Е. Игнорирует его), тогда метод реализации является необработанным. И когда метод считается необработанным, компилятор игнорирует всю общую информацию (в том числе и в возвращаемом типе). Обратите внимание, что это, однако, не применяется к методам, которые просто * возвращают * общий тип и не реализуют другой метод. –

0

вы должны написать так:

public interface AnInterface<T> { 
    Consumer<T> getConsumer(); 
} 

public class AClass implements AnInterface<String> { 
    @Override 
    public Consumer<String> getConsumer { 
     return System.out::println; 
    } 
} 
+0

Убей меня :) –

+1

Да, это правильный подход, но на самом деле это не касается * почему * работает другая форма. – Makoto

+0

... вот что мой ответ пытается сделать :) –

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