java - 为什么派生类有时只能在重写方法中具有特殊类型?

标签 java polymorphism

假设我有这个基类:

abstract public class Base {
    abstract public Map save();
    abstract public void load(Map data);
}

令我惊讶的是,我可以在派生类中执行此操作:

public class Derived extends Base {
    @Override
    public Map<String, String> save() {    //Works
        ...
    }
    ...
}       

但我做不到:

public class Derived extends Base {
    @Override
    public void load(Map<String, String> data) {    // Fails
        ...
    }
    ...
}       

这里发生了什么?为什么我可以使用专门的返回类型但不能使用专门的参数类型?

更令人困惑的是,如果我保留 load 的原始声明,我可以将其分配给更特殊的类型:

public class Derived extends Base {
    @Override
    public void load(Map data) {
        Map<String, String> myData = data;   // Works without further casting
        ...
    }
    ...
}       

最佳答案

存在从专用类型到原始类型的隐式转换 - 这始终是“安全的”,因为使用原始类型的人无法做出任何假设。所以有人希望得到一个原始的Map从方法返回并不介意他们是否得到 Map<String, String> .

如果有人传递原始 Map ,则不存在从原始类型到专用类型的隐式转换。进入load它可能有非字符串键和值。根据 load 的基类型声明,这是完全合法的。 .

抛开泛型不谈,你的方法有点像这样:

public abstract class Base
{
    public abstract Object save();
    public abstract void load(Object x);
}

public class Derived extends Base
{
    @Override
    public String save() { ... } // Valid

    @Override
    public void load(String x) // Not valid
}

删除泛型后,是否清楚为什么 save在这里打电话是可以的,但是 load打电话不是吗?考虑一下:

Base b = new Derived();
Object x = b.save(); // Fine - it might return a string
b.load (new Integer(0)); // Has to compile - but the override wouldn't work!

关于java - 为什么派生类有时只能在重写方法中具有特殊类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/776768/

相关文章:

java - 如何强制转换以运行父类(super class)方法

scala - 如何从投影类型推断正确的类型参数?

C++ - 不需要使用基本方法

java - 处理子类中不需要的参数? (java)

java - 使用 for 循环重复字符串

java - log4j2 中的 PatternLayout < > 转义字符

java - Martin Odersky 演讲中 Scala 编译器早期实现中的可重入性和静态数据。它们有何关系?

java - 使用java和套接字的简单聊天程序

python - Flask 基于类的 View ——多态性

java - 帮助第一个多态性类