Вопрос о ковариантных параметрах в Java - PullRequest
0 голосов
/ 18 января 2020

У меня есть этот фрагмент кода:

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

Я знаю, что есть некоторые ошибки, такие как ковариантный тип возврата в

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()); он вызывает метод 1 из A, но другой я не понимаю).

Спасибо!

1 Ответ

0 голосов
/ 18 января 2020

Метод в подклассе не может нарушать контракт в суперклассе, поэтому предположим, что у вас есть

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

, тогда любой SubClass должен либо переопределить метод с помощью

ReturnType method(ParameterType p) {..}

или

ReturnTypeSubclass method(ParameterType p) {..}

Это гарантирует, что при использовании класса не будет проблем с типами. Контракт не нарушается с ковариантными типами возврата, потому что ReturnTypeSubClass является ReturnType.


Если вы реализуете метод в SubClass, например, так:

AnyType method(ParameterTypeSubClass p) {..}

..вы не переопределите это. Вы перегружаете это. Теперь есть два метода в SubClass. Один унаследован от SuperClass.

Представьте, что если он переопределяет его и кто-то использует класс следующим образом:

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

будет выдана ошибка, поскольку метод переопределения не будет может взять ParameterType, и контракт будет расторгнут.

...