关于 Java 中协变参数的问题

Question about covariant parameters in Java

我有这段代码:

class X {
    int x = 1;
}

class Y extends X {
    int y = 2;
}

class Z extends Y {
    int z = 3;
}


class A {
    public Y metodo1(Y y) {
        System.out.println("Metodo1 de A");
        return new Y();
    }

    public Y metodo2(Y y) {
        System.out.println("Metodo2 de A");
        return new Y();
    }
}

class B extends A {
    public X metodo1(Y y) {
        System.out.println("Metodo1 de B");
        return new X();
    }

    public Z metodo2(Y y) {
        System.out.println("Metodo2 de B");
        return new Z();
    }

    public void metodo3() {
        System.out.println("Metodo3 de B");
    }
}

class C extends A{
    public Y metodo1(X x) {
        System.out.println("Metodo1 de C");
        return new Y();
    }

    public Y metodo2(Z z) {
        System.out.println("Metodo2 de C");
        return new Z();
    }

    public void metodo3() {
        System.out.println("Metodo3 de C");
    }
}

public class DynamicBinding {
    public static void main(String[] args) {
        A b = new B();
        A c = new C();
        C c1 = new C();

        X x1 = b.metodo1(new Y());
        X x2 = b.metodo2(new Y());
        b.metodo3();

        X x3 = c.metodo1(new X());
        X x4 = c.metodo2(new Z());
        c.metodo3();

        X x5 = c1.metodo1(new Y());
        X x6 = c1.metodo1(new X());
    }
}

我知道有一些错误,例如

中的协变 return 类型
public X metodo1(Y y) {
      System.out.println("Metodo1 de B");
      return new X();
} 

或者 b.metodo3(); 不存在,但我的问题是:

X x5 = c1.metodo1(new Y());
X x6 = c1.metodo1(new X());

Eclipse 没有向我显示任何错误,但我认为它们具有协变参数,这在 Java 中是不允许的。我错过了什么? (可能在X x5 = c1.metodo1(new Y());里面调用了A的metodo1,但是另一个我看不懂)

谢谢!

不允许子 class 中的方法破坏超级 class 中的约定,所以假设您有

Class SuperClass{
  ReturnType method(ParameterType p) {..}
}

然后任何 SubClass 必须使用

覆盖方法
ReturnType method(ParameterType p) {..}

ReturnTypeSubclass method(ParameterType p) {..}

这确保了在使用 class 时,类型没有问题。协变 return 类型没有违反合同,因为 ReturnTypeSubClassReturnType.


如果您像这样在 SubClass 中实现方法:

AnyType method(ParameterTypeSubClass p) {..}

..你没有覆盖它。你超载了它。 SubClass中现在有两个方法。一个是继承自SuperClass.

想象一下,如果它覆盖了它并且有人像这样使用 class:

Super s = new SubClass;
s.method(new ParameterType());

会抛出一个错误,因为覆盖方法将无法接受 ParameterType,并且合同会被破坏。