Polymorphisme étonnant: Java ne privilégie pas les méthodes aux objets spécialisés?
J'en ai perdu mon latin et suis très embarrassé par les implications d'une expérience que j'ai menée.
Deux objets A et B ont une fonction toString() qui renvoie "A" et "B".
B hérite de A.
Code:
1 2 3 4 5 6 7 8 9 10
|
public class A
{
public String toString() {return("A");}
}
public class B extends A
{
public String toString() {return("B");}
} |
Une classe C est munie de deux méthodes toString(X x) prenant ces classes en argument:
Code:
1 2 3 4 5 6 7
|
public class C
{
public String toString(A a) {return("C voit A");}
public String toString(B b) {return("C voit B");}
} |
Voici ce que j'expérimente:
Code:
1 2 3 4 5 6 7
|
C c = new C();
A a1 = new A();
B b1 = new B();
System.out.printf("a1 = %s, b1 = %s\n", a1, b1);
System.out.printf("c.toString(a1) = %s, c.toString(b1) = %s\n", c.toString(a1), c.toString(b1)); |
Résultat (sur la console):
a1 = A, b1 = B
c.toString(a1) = C voit A, c.toString(b1) = C voit B
C'est ce à quoi je m'attendais.
Mais:
Code:
1 2 3 4
|
A a2 = new B();
System.out.printf("a2 = %s\n", a2);
System.out.printf("c.toString(a2) = %s\n", c.toString(a2)); |
Produit:
a2 = B
c.toString(a2) = C voit A
D'un côté, Java a bien remarqué que a2 était un objet de classe B, puisqu'il dit a2 = B,
D'un autre côté, il ne choisit pas le prototype de toString(X x) dans C que j'attendais, car il prend celui pour A.
Code:
1 2 3 4 5 6
|
B b3 = new B();
A a3 = (A)b3;
A a4 = b3;
System.out.printf("a3 = %s, b3 = %s, a4 = %s\n", a3, b3, a4);
System.out.printf("c.toString(a3) = %s, c.toString(b3) = %s, c.toString(a4) = %s\n", c.toString(a3), c.toString(b3), c.toString(a4)); |
Ces autres essais mènent aux mêmes constatations:
a3 = B, b3 = B, a4 = B
c.toString(a3) = C voit A, c.toString(b3) = C voit B, c.toString(a4) = C voit A
Et cela ne me convient pas du tout!
Cela ne vous choque t-il pas?