为什么java方法重写允许有协变返回类型,而不是协变参数?

时间:2017-10-21 09:19:38

标签: java covariant

例如,我有一个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 个答案:

答案 0 :(得分:10)

The Liskov principle。在设计Processor类时,你写了一个合同说:“一个处理器能够将任何Object作为参数,并返回一个Object”。

StringProcessor是一个处理器。所以它应该服从那份合同。但如果它只接受String作为参数,它就违反了该合同。请记住:处理器应该接受任何Object作为参数。

所以你应该能够做到:

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;
    }
}

返回String时,它不违反合同:它应该返回一个Object,一个String就是一个Object,所以一切都很好。

您可以使用泛型来实现您想要达到的目标:

10,000! ~= 10^36,000

答案 1 :(得分:0)

另外,如果你想要一个类型理论答案,原因是,当考虑函数类型的子类型关系时,关系在返回类型上是协变的,但在参数类型上是逆变(如果X -> YU -> W的子类型且YW的子类型,则UX的子类型。