Почему в java-методе переопределение позволяет иметь ковариантные возвращаемые типы, а не ковариантные параметры?

Например, у меня есть базовый класс Processor с методом, который возвращает Object и принимает Object в качестве параметра. Я хочу расширить его и создать StringProcessor, который будет возвращать String и принимать String в качестве параметра. Однако ковариантная типизация допускается только с возвращаемым значением, но не с параметром. В чем причина таких ограничений?

class Processor {
    Object process (Object input) {
        //create a copy of input, modify it and return it
        return copy;
    }
}

class StringProcessor extends Processor {
    @Override
    String process (String input) { // permitted for parameter. why?
        //create a copy of input string, modify it and return it
        return copy;
    }
}

2 ответа

Принцип Лискова. При разработке класса Processor вы пишете контракт, в котором говорится: "Процессор может принимать любой объект в качестве аргумента и возвращать объект".

StringProcessor является процессором. Так что он должен подчиняться этому контракту. Но если он принимает только String в качестве аргумента, он нарушает этот контракт. Помните: процессор должен принимать любой объект в качестве аргумента.

Так что вы должны быть в состоянии сделать:

StringProcessor sp = new StringProcessor();
Processor p = sp; // OK since a StringProcessor is a Processor
p.process(new Integer(3456));

Возвращая строку, он не нарушает контракт: он должен вернуть объект, строка - это объект, поэтому все в порядке.

Вы можете сделать то, что вы хотите достичь, используя дженерики:

class Processor<T> {
    Object process (T input) {
        //create a copy of input, modify it and return it
        return copy;
    }
}

class StringProcessor extends Processor<String> {
    @Override
    String process (String input) { 
        return copy;
    }
}

Кроме того, если вы хотите получить теоретический ответ, причина этого заключается в том, что при рассмотрении отношения подтипа для типов функций отношение является ковариантным для возвращаемых типов, но противоречивым для типов аргументов (т.е. X -> Y это подтип U -> W если Y это подтип W а также U это подтип X).

Другие вопросы по тегам