Cast d'objet java, problème de comportement

Le problème exposé dans ce sujet a été résolu.

Bonjour,

J’ai une petite question concernant le cast d’objet en java, il y a quelque chose qui m’echappe. Prenons les classes suivantes :

1
2
3
4
5
6
7
class A {
}

class B extends A {
    public void t(A a) { System.out.println("a"); }
    public void t(B b) { System.out.println("b"); }
}

et le code suivant :

1
2
3
4
5
6
7
8
9
A a = new A(); 
B b = new B();

b.t(a); // Selon moi, affiche a --> OK
b.t(b); // Selon moi, affiche b --> OK

a = b;
System.out.println(a.getClass()); // Selon moi affiche Class b --> OK
b.t(a); // Selon moi affiche b --> NON

On a la sortie suivante :

1
2
3
4
a
b
class B
a

Pourquoi après a = b, quand on appelle la méthode t(a), c’est la méthode t(A a) qui est appelé alors que a est instance de la classe B ?

+0 -0

Salut, je viens de tester et ça affiche bien b à la fin :

1
2
3
4
A@2a139a55
B@15db9742
class B
B@15db9742

D’ailleurs ton code ne compile pas (j’ai du rajouter le type devant les noms de variables lors de leur déclaration).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class A {
}

class B extends A {
    public void t(A a) { System.out.println(a); }
    public void t(B b) { System.out.println(b); }
}

class Playground {
    public static void main(String[ ] args) {
        A a = new A();
        B b = new B();

        b.t(a);
        b.t(b);

        a = b;
        System.out.println(a.getClass());
        b.t(a);
    }
}
+0 -0

Oui effectivement désolé, dans le code que je vous ai mis, j’affiche les objets, j’avais oublié de mettre les guillemets, je voulais afficher les chaines de caractères "a" et "b". J’ai modifié mon code.

Effectivement c’est logique que ça affiche l’objet b, mais alors pourquoi c’est la fonction t(A a) qui est appelée ? …

Vous pouvez executer le code ici : http://tpcg.io/gha1i4

+0 -0

En effet, et c’est normal, je t’invite à lire ce sujet pour avoir plus d’informations : https://stackoverflow.com/questions/1572322/overloaded-method-selection-based-on-the-parameters-real-type

En fait, ce qu’on appelle le dispatch dynamique (appeler la bonne méthode en fonction du vrai type de l’objet et non du type de la référence) ne se fait que sur l’objet lui-même (le this, d’où l’intérêt de surcharger des méthodes) mais pas sur pour les types des paramètres des méthodes. Donc, ta référence est de type A et contient un objet de type B, autreObjet.methode(monObjetBDansRefA) appelera methode(A a). Par contre, on a bien le comportement voulu pour monObjetBDansRefA.methodeSurchargée() qui appelera la méthode surchargées dans la classe B.

EDIT : le multi-dispatch, c’est-à-dire vraiment choisir tous les "bons" types, c’est possible dans certains langage mais assez peu. Pour les autres, on peut l’emuler (via le design pattern visitor entre autre), voir https://en.wikipedia.org/wiki/Multiple_dispatch

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte