question consernant un code contenant : instanceof

question consernant un code contenant : instanceof - Java - Programmation

Marsh Posté le 02-02-2008 à 20:54:11    

Bonsoir,
 
J'ai trouvé sur un document de java, un cet exemple:
 

Code :
  1. void afficheChaine(Object o)
  2. {
  3.    if (o instanceof MaClasse)
  4.    {
  5.       MaClasse m = (MaClasse) o;
  6.       System.out.println(m.getChaine());
  7.       // OU System.out.println( ((MaClasse) o).getChaine() );
  8.    }
  9. }


 
Et je ne comprends pas pourquoi il faut faire un cast de l'objet o vers le type MaClass.
Ou alors je ne comprends pas comment l'objet o peut-il être un instance de la class MaClass alors qu'il est passé en argument à la fonction afficheChaine() comme étant de type o.
 
à moin que ça soit une propriété de l'héritage entre les objets de class Object et les ceux de MaClass !?
 
Merci


Message édité par robocop333 le 02-02-2008 à 20:54:39
Reply

Marsh Posté le 02-02-2008 à 20:54:11   

Reply

Marsh Posté le 02-02-2008 à 21:08:06    

J'inverse les questions :

Citation :

Ou alors je ne comprends pas comment l'objet o peut-il être un instance de la class MaClass alors qu'il est passé en argument à la fonction afficheChaine() comme étant de type o.


En java, tout objet hérite implicitement d'Object. Par exemple pour la jdk :
http://java.sun.com/j2se/1.4.2/doc [...] -tree.html
 

Citation :

Et je ne comprends pas pourquoi il faut faire un cast de l'objet o vers le type MaClass.


Cf réponse ci-dessus et la méthode getChaine() est définie pour les objets de type MaClasse, et non pour les objets de type Object.


Message édité par charly007 le 02-02-2008 à 21:10:58
Reply

Marsh Posté le 03-02-2008 à 10:06:47    

Donc o est une instance de Maclass.

 

Mais puisqu'il est passé en argument à la fonction afficheChaine(Object o), il est copié dans le paramètre "Object o" et c'est autorisé car Object est une class mère de Maclasse (puisque tout objet hérite implicitement d'Object).

 

Et puisque la méthode getChaine() est définie pour seulement la class MaClasse, Je dois faire un cast de l'objet o vers MaClasse pour pouvoir utilisé cette methode.

 

( et ceci car si une class fille hérite d'une class mère ) et qu'on copie un objet de type "classFille" dans un objet déclarer de type "classMère", alors seulement les méthode -et attributs- hérité par la fille de la mère, sont copié ).

 

Est ce que ce que je raconte est correct ou ya quelque chose que j'ai pas compris ?

 

Merci


Message édité par robocop333 le 03-02-2008 à 10:07:02
Reply

Marsh Posté le 04-02-2008 à 17:47:53    

C'est presque bon :
 
( et ceci car si une class fille hérite d'une class mère ) et qu'on copie un objet de type "classFille" dans un objet déclarer de type "classMère", alors seulement les méthode -et attributs- hérité par la fille de la mère, sont visibles ).

Reply

Marsh Posté le 05-02-2008 à 00:42:26    

Pour comprendre cela, il faut réaliser que Java est un langage compilé et à typage fort, pour lequel l'essentiel du typage est vérifié à la compilation et non à l'exécution (contrairement à la plupart des langages objets interprétés).
 
Il faut donc dissocier le type de l'objet au moment de la compilation, et son type à l'exécution. A la compilation, le type de l'objet, c'est celui de la variable au travers de laquelle tu le manipules. Et sur un objet, on ne peut invoquer une méthode (ou accéder à un attribut) que si celle-ci (ou celui-ci) est défini pour ce type. Chose que vérifie le compilateur avec les informations dont il dispose (et il ne dispose que du type de la variable, que j'appelle le "type à la compilation" de l'objet).
 
A l'exécution, on considère le type réel de l'objet, c'est-à-dire celui qui a servi à le construire (opération new), et ce type-là peut être différent du type utilisé pour déclarer la variable (même si les 2 types doivent impérativement être liés par une relation d'héritage direct ou indirect : c'est le compilateur qui s'en assure).
 
Typiquement, ici, le type à la compilation de "o", c'est Object. Donc sur cette variable, et l'instance qu'elle permet de manipuler, on ne peut appeler que des méthodes définies sur la classe Object.
Mais si l'instance que permet de manipuler o a été créée de type MaClasse ("... = new MaClasse()" ), alors la JVM permet de faire un cast sur cette variable, qui crée une expression de type MaClasse (et non plus seulement Object) à partir de cet objet. Et puisque cetle expression ("(MaClasse) o" ) est de type (à la compilation) MaClasse, on peut y faire tout ce qu'on peut faire sur une instance de ce type (en particulier invoquer une méthode ou accéder à un attribut définis sur ce type).

Reply

Marsh Posté le 05-02-2008 à 10:27:18    

Ok, je vois mieux now.

 

J'ai une autre petite question qui n'as pas de relation avec la précédente:

 

Y a il une différence entre faire:

Code :
  1. MaClass truc = toto;


Et faire:

Code :
  1. MaClass truc = new MaClass(toto);


?


Message édité par robocop333 le 05-02-2008 à 22:09:52
Reply

Marsh Posté le 05-02-2008 à 19:56:04    

On suppose bien sûr ici que toto est déclaré de type MaClasse.
 
Et oui, il y a une différence, et elle est énorme... Curieux qu'on ne t'aies pas bien expliqué cela, c'est un point absolument fondamental de Java (comme de la grande majorité des langages objet).
 
Souviens-toi qu'en Java, tout objet se manipule par référence. Ce qui signifie que toto ne contient pas l'objet, il contient (grosso modo) l'adresse en mémoire de cet objet. Donc quand tu écris :

Code :
  1. truc = toto;


tu recopies dans la variable truc (qui peut contenir une adresse mémoire) l'adresse mémoire contenue dans la variable toto. Autrement dit, derrière les variables truc et toto, c'est le même objet. Et donc, toute manipulation que tu feras sur l'objet référencé par toto, aura également lieu sur l'objet derrière la variable truc, puisque c'est le même objet.
 
Alors que quand tu écris :

Code :
  1. truc = new MaClasse(toto);

tu commences par créer un nouvel objet (opération new), et le new te retourne l'adresse mémoire du nouvel objet créé... qui n'est pas le même objet que celui de toto, puisque, on vient de le dire, il est nouveau.
 
Note : Souvent, cette dernière écriture, appelée appel du constructeur par recopie, est utilisée pour créer un second objet dont le contenu est identique au premier (écriture d'ailleurs déconseillée en Java : on préfère largement utiliser la méthode clone(), qui marche dans bien plus de cas que le constructeur par recopie). Attention : "2 objets au contenu identique", ce n'est pas la même chose que "le même objet" (c'est ce que différencient la méthode equals() et l'opérateur ==).
 
Capici ?

Reply

Marsh Posté le 05-02-2008 à 22:05:31    

Merci BifaceMcLeOD, je dois avoué que c'est une très bonne explication.

 

Je vois donc, pour le 1er cas: toto et truc vont pointé sur le même objet.
Et dans le 2eme, on crée une nouvelle instance qui as le même contenue que toto.

 


Mais, et dans le cas où je n'utilise pas toto, je veut dire par exemple:

 
Code :
  1. String texte = "Hello";
  2. /* est ce que c'est identique à : */
  3. String texte = new String("Hello" );
 

Je croie que c'est la même chose puisqu'on utilise une chaine constance "Hello", pour créer une instance pour l'objet texte, dans les deux cas. Mais je ne suis pas sure.


Message édité par robocop333 le 05-02-2008 à 22:11:03
Reply

Marsh Posté le 06-02-2008 à 22:56:20    

Dans ce genre de situation, je te conseille vivement de faire le test toi-même : écris une petite classe Java qui contient juste un main() avec les quelques instructions qui répondent à ta question. Même après des années d'expérience, tu verras que tu continueras à apprendre des trucs comme ça en Java (ou d'autres environnements).
 
Je vais quand même répondre à ta question (mais pour être sûr de ne pas dire de bêtises sur le dernier point de mon post, j'ai pris 2 minutes pour faire exactement ce que je te conseille ci-dessus : écrire une toute petite classe Java qui teste ce que je voulais vérifier).
Non ce n'est pas la même chose : le "new String(...)" crée forcément une nouvelle instance de String.
 
Attention cependant, la gestion des instances de String est un peu particulière en Java (par rapport aux autres classes), parce que String est très très utilisée. Si on écrit :

Code :
  1. String texte1 = "Hello";
  2. String texte2 = "Hello";

dans le principe, texte1 et texte2 devraient référencer des objets différents (et de même contenu). Mais dans le cas particulier de String, la JVM optimise tout ça, détecte qu'il s'agit de la même valeur constante dans les 2 cas. Résultat : texte1 et texte2 se retrouvent à référencer la même instance de String.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed