java - 为什么在 java 方法重写中允许具有协变返回类型,但不允许协变参数?

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

最佳答案

The Liskov principle 。在设计 Processor 类时,您写了一个契约说:“一个 Processor 能够将任何 Object 作为参数,并返回一个 Object”。

StringProcessor 是一个处理器。所以它应该遵守那个契约(Contract)。但是如果它只接受 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;
    }
}

关于java - 为什么在 java 方法重写中允许具有协变返回类型,但不允许协变参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46861804/

相关文章:

Java协变返回类型

arrays - Ada 中的数组是协变的吗?

java - 如何使用 SeekBar 以编程方式调整设备亮度?

java - netbeans 输出线重叠

java - 关闭浏览器时 session 丢失

java - Android Mediaplayer Streaming - 现在工作但没有

c# - 没有 I/O 的等待开销是多少?

Java协变数组不好吗?

c++ - 协变返回类型

尝试在 Linux 上打开文件时出现 Java Nullpointer 异常