0

I have this piece of code:

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

I know there are some errors like the covariant return type in

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

or that b.metodo3(); doesn't exist, but my question is about this:

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

Eclipse doesn't show me any errors, but I think that they have covariant arguments and that is not allowed in Java. What am I missing? (maybe in X x5 = c1.metodo1(new Y()); it calls the metodo1 of A, but I don't understand the other one).

Thanks!

Awacate
  • 125
  • 2
  • 10
  • C has a method taking an X as argument. so the argument matches. And it returns an Y. An Y is an X, so you can assign the result to a variable of type X. – JB Nizet Jan 18 '20 at 14:25
  • "*... that they have covariant arguments and that is not allowed in Java*" - Why should it not be allowed? `metodo1(X x)` in `C` does not override `medoto1(Y y)` in `A`, but overload it. You can verify this by adding `@Override` to `metodo1(...)` in class `C`. This will result in a compiler error. – Turing85 Jan 18 '20 at 14:26
  • Oh okay now I see it, it seems that I have misread the exercise :) Thank you both! – Awacate Jan 18 '20 at 14:50

1 Answers1

0

A method in a sub class is not allowed to break the contract in a super class, so lets assume you have

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

then any SubClass must either override method with

ReturnType method(ParameterType p) {..}

or

ReturnTypeSubclass method(ParameterType p) {..}

This ensures that when the class is used, there's no issues with types. The contract isn't broken with covariant return types, because ReturnTypeSubClass is a ReturnType.


If you implement method in SubClass like so:

AnyType method(ParameterTypeSubClass p) {..}

..you're not overriding it. You're overloading it. Now there are two method in SubClass. One is inherited from SuperClass.

Imagine if it was overriding it and someone used the class like so:

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

an error would be thrown, because the overriding method would not be able to take a ParameterType, and the contract would be broken.

Scratte
  • 3,056
  • 6
  • 19
  • 26
  • Yeah I knew the theory but it seems that the problem is that I have misread the exercise. Anyways it's a very good explanation so I'll mark it as the correct answer, thanks! – Awacate Jan 18 '20 at 17:32
  • @MarioR. Thank you. I tested it all before I posted it, just to make sure :) – Scratte Jan 18 '20 at 18:08