2013-08-12 2 views

ответ

5

Вы не можете переопределить метод объявлен как

void say(List<? extends Number> list) // A 

с

void say(List<Number> list)    // B 

просто потому, что типы не эквивалентны. Например, List<Integer> соответствует List<? extends Number> но не List<Number>, так

List<Integer> integers = Arrays.<Integer>asList(1, 2, 3); 
a.say(integers); // is valid assuming signature A 
b.say(integers); // does not compile 

(см этот вопрос для получения подробной информации о generics, wildcards, and type relationships). Если компилятор сделал позволит вам переопределить так, как вы хотите, то следующий будет возможно:

class A { 
    void say(List<? extends Number> numbers) { } 
} 

class B extends A { 
    void say(List<Number> numbers) { numbers.add(Double.valueOf(1.0)); } 
} 


List<Integer> onlyIntsPlease = new ArrayList<Integer>(); 
B b = new B(); 

// Oops! The list of `Integer` will now contain a `Double`... 
b.say(onlyIntsPlease); 
2

Это невозможно как на общих теоретических основаниях и в связи со спецификой Java дженериков.

Общий принцип заключается в том, что основной метод должен быть заменяемым для метода базового класса. Например, метод подкласса может использовать расширенный модификатор доступа, но не более узкий. В вашем случае,

void say(List<Number> list) 

более ограничительный, чем

void say(List<? extends Number> list) 

так что это явно нарушает принцип заменимости.

Практического препятствие заключается в следующем: наиважнейший о выполнение полиморфизма, в то время как Дженерик о время компиляции полиморфизма и параметры типа экземпляра не доступны даже к механизму способа доставки.

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