7

例如,我有一个处理器基类,其方法返回一个对象并将对象作为参数。我想扩展它并创建一个 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;
    }
}
4

2 回答 2

14

里氏原理。在设计处理器类时,您编写了一个合同说:“处理器能够将任何对象作为参数,并返回一个对象”。

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

所以你应该能够做到:

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

返回 String 时,并不违反约定:它应该返回一个 Object,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;
    }
}
于 2017-10-21T09:24:43.070 回答
2

此外,如果您想要一个类型理论的答案,其原因是,在考虑函数类型的子类型关系时,该关系在返回类型上是协变的,但在参数类型上是逆变的(即if子类型是并且是) 的子类型。X -> YU -> WYWUX

于 2017-10-21T12:01:56.793 回答