简体   繁体   中英

Polymorphism doesn't work as expected, why?

I have these 2 classes in my java program:

public class A {
    private final static A five = new A(5);
    public final int x;
    public A(int x) {
        this.x = x;
    }
    public boolean equals(Object o) {
        return x == ((A) o).x;
    }
    public String toString() {
        return equals(five) ? "five" : (x + "");
    }
}

public class B extends A {
    public final int x;
    public B(int x) {
        super(x);
        this.x = x + 1;
    }
    public boolean equals(A o) {
        return x == o.x;
    }
    public String toString() {
        return "B: " + super.toString();
    }
}

Now in my main i'm doing these 2 simple actions:

public static void main(String[] args) {
    System.out.println(new A(5));
    System.out.println(new B(5));
}

About the first line, as i expected, it will create an A object -> go to A's toString function -> get True for the equals function and finally print "five".

About the B, what i expected and what actually happening is different... I thought it will go to B's constructor -> go to A constructor and assign the number 5 to x -> return to B constructor and assign the number 6 to B's x -> go to B's toString method and print "B: " (Until this point i was right) -> go to A's toString -> go to B's equals since the object type is B and that's what you looking at concerning method activation (* This is where i was wrong) -> return False because the x in B is 6 -> print the number 5 since we were in A's toString .

Instead, in the part where it's calling the A class toString instead of going to the B equals method it's staying in A and activate the A equals ...

I have no idea why is it happening, all i know is the method activated is determined by the object type.

Hope someone could explain me what's different here... Thanks!

To expand on your answer, for future readers:

In A.toString() you call this.equals(five) , where five is of type A .

In the context of A, the only equals() method matching A is A.equals(Object o) . So that is the method the JVM calls.

If there were an overriding method B.equals(Object o) then this would have been called. It's not enough that there is a B.equals() method with a narrower type.

You can get the behaviour you expected by either supplying an A.equals(A a) method, or by expanding the breadth of B.equals() to take Object .

A couple of notes:

  • In only a few lines you've created something pretty intricate here. I hope it's just to experiment: real code should be much more straightforward.
  • If you're going to implement equals() make it accept Object , so you're overriding the standard method.

正如给出的注释所解释的那样,我没有重写函数,而是使用对该方法全​​新的签名重载了该函数。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM