10
votes

Question sur le polymorphisme et la coulée Java

J'ai une classe C. Classe E l'étend.

((M) k).doIt();


0 commentaires

9 Réponses :


7
votes

juste parce que e s'étend c, c ne devient pas un e ... e d'autre part est un c

edit: Pour développer le commentaire de Mark ci-dessous ... Juste parce que chaque femme est un humain, tous les humains ne sont pas des femmes. Tous les humains partagent l'interface humaine avec les jambes, les mains, les visages, etc. Les femmes l'étendent avec des fonctionnalités qui renvoient de bons sentiments lorsque vous fournissez des diamants et de l'or.

La double conversion INT => n'est même pas liée car ce n'est pas un casting de classe, mais une conversion indiquant au compilateur de stocker tout ce qui est dans X dans Y (qui se trouve être un double).

((m) k) .getclass () donne k.

parce que k est toujours un k même si vous le jetez à un m ou à un objet (ou quelque chose d'autre, il se trouve être).

EDIT: Je pense que la confusion ici est que vous considérez que k doit "devenir" un m quand vous le jetez, ce n'est pas le cas. Vous ne le traitez que comme M. Si vous demandez à quelqu'un qui est un "propriétaire de chien" quel genre de race il est qu'il ne retournera pas "c'est un chien", la raison est simplement que la méthode GetBreedName () aura probablement été remplacée dans le sous-classe Labradorworker pour revenir " Labrador". C'est la même chose avec GetClass (), il retournera la classe de la mise en œuvre. Ce ne sera pas un m mais un k qui arrive à être un M aussi juste parce que k s'étend m.


6 commentaires

Pourquoi pas? Chaque E est un C. donc pourquoi je ne peux pas traiter un objet C comme e? Pour la deuxième partie - alors que fait le casting? Cela ne change pas la variable. Que se passe-t-il si j'exécute ((m) k) .doIt () - K's ou m's Doit () sera exécuté?


Vous pouvez aussi bien demander: chaque femme est une personne; Pourquoi ne puis-je pas traiter toutes les personnes comme une femme? Réponse: vous peut - mais d'abord, vous devez vérifier qu'ils sont une femme.


Chaque E est un c mais pas tous les C est un E. E étendre C est comme dire que c'est indiquer que e ajoute à C par conséquent, un C pourrait ne pas avoir la même quantité de choses qu'il y a un.


Merci Marc et Russ pour remplir les blancs comme des commentaires. Je ne suis pas sûr de savoir si cela signifie quelque chose pour marquer des commentaires aussi géniaux, mais je les ai accueillis une fois chacun.


@Fredrik: Vous devriez avoir envie de profiter des Atributes de Wiki, et de modifier votre réponse pour clarifier. :)


Bien sûr, je viens de sentir que les commentaires l'ont dit tout et que quiconque voyant la réponse se verra voir les commentaires.



4
votes

Le int code> / double code> n'est pas liée; C'est une conversion, pas un casting - il n'y a pas de relation entre int code> et double code>.

RE LA QUESTION; L'objet d'un type est fixé à la création. Un objet fort> qui est un C code> n'est pas em> (et ne peut jamais être) un E code>. Cependant, vous pouvez traiter em> un E code> en tant que C code>, car l'héritage représente "est un". Par exemple: p> xxx pré>

ici, nous n'avons toujours qu'un seul objet - simplement que la variable c code> y réfléchit comme un C code >, donc ne pas exposer les méthodes spécifiques à E code> (même si l'objet est strong> un E code>). p>

si Nous ajoutons ensuite: P>

E secondE = (E) c;


4 commentaires

Merci. Pouvez-vous donner un exemple où e seconde = (e) c; travaillerait?


Il a juste fait ... quand vous faites: e e = nouveau e (); C c = e puis faire un e à nouveau avec "e seconde = (e) c"; Étant donné que l'objet a été un e tout le temps (même si quelqu'un l'a traité comme le C c'est-il par héritage), la troisième rangée sera parfaitement légale.


Dans le code réel BTW, la troisième ligne serait probablement à l'intérieur de certains "si (C Instance de E)". Si vous saviez tout le temps que votre C est un E, il ne serait pas logique de le jeter à un C en ligne deux.


J'aurais eu une question similaire et j'ai trouvé ce fil. Votre réponse m'a aidé à comprendre le sujet.



0
votes

Pour la première question, vous ne pouvez pas lancer une superclasse à une sous-classe, car une sous-classe ajoute des membres que la superclasse n'a pas. Comment le compilateur est-il censé savoir quelles valeurs à y mettre quand il monder? Fondamentalement, un e est un c, mais un c n'est pas un e.

getclass () obtient le type de l'objet en mémoire. Le casting à m masque simplement le fait que c'est un k, cela ne change pas l'objet sous-jacent.


0 commentaires

8
votes

Vous ne pouvez pas lancer d'objets en Java.

Vous pouvez lancer des références en Java.

Casting d'une référence ne change rien sur l'objet qu'il fait référence. Il ne produit qu'une référence d'un type différent pointant vers le même objet que la référence initiale.

Les valeurs primitives de casting sont différentes des références de coulée. Dans ce cas, les valeurs font le changement .


0 commentaires

1
votes

Pour ajouter à la réponse de Frederik, jetant un objet à quelque chose ne change pas son type. En outre, l'objet peut seulement être jeté à un type qu'il est déjà (le compilateur ne sait pas à ce moment-là) C'est pourquoi des cases impossibles ne seront jamais acceptées:

Integer i = (Integer) new String();


0 commentaires

17
votes

Considérez un exemple réel:

public void amuseAnimals( List<Animal> animals ) {
    for ( Animal animal : animals ) {
         if ( animal instanceof Dog ) {
             Dog doggy = (Dog)animal;
             doggy.takeForWalk( new WalkingRoute() );
         } else if ( animal instanceof Cat ) {
             Cat puss = (Cat)animal;
             puss.play( new BirdShapedToy() );
         }
     }
}


2 commentaires

Pourquoi exécute-t-il DOIT de K? Je dis à faire référence à cet objet en tant que M et non à K. Si le compilateur le traite comme un M, il devrait exécuter les méthodes de M. Je suis encore plus confus maintenant. Pouvez-vous donner un exemple de casting (chien chien = (chien) myanimal) a du sens?


"Si le compilateur le traite comme un M, il devrait exécuter les méthodes de M.". Le compilateur le traite comme un M pour des raisons de taper. Si k ne peut pas être tapé comme une m, une clascastexception est lancée. Les méthodes de K sont utilisées car comme une sous-classe K peut remplacer les méthodes de M. C'est ce qui sépare une K d'un M et est une partie intrinsèque de l'orientation objet.



1
votes

(m) k) .getclass () donne K. pourquoi est-ce? Il a été lancé au plus général m!

Une analogie utile (que j'ai eu du site de Bill Venners 'Artima.com) qui pourrait aider à préciser la confusion est que la différence entre les classes et les objets est comme la différence entre le plan d'architecte et la maison actuelle construite. Le plan directeur existe sur papier et est un concept, tandis que la maison existe dans la vie réelle. Vous pouvez avoir plus d'une maison construite au même plan.

Comment cela est-il pertinent pour cette question? Disons qu'il y ait un McMansion Blueprint et un McMansionwithheatedpool Plutier. Un McMansionWithheatedpool est une extension d'un MCMansion avec une piscine chauffée.

Maintenant, si vous voyez un vrai McMansionwithheatedpool , pour cet objet:

  1. conceptuellement (c'est-à-dire si vous regardez les Blueprints de l'architecte), vous verriez qu'un McMansionwithheatedpool est clairement également un McMansion . Par conséquent, le refonte est autorisé. (Pour la même raison, un objet McMansion ne peut pas être taper de manière à jeter dans un McMansionwithheatedpool : Pas de piscine chauffée!)

  2. (( MCMansion ) k) .getclass () donne McMansionwithheedpool car k est toujours un McMansionwithheatepool . La fonte de type est sur l'expression, pas sur l'objet.


0 commentaires

1
votes

"Si le compilateur le traite en tant que M, il devrait exécuter les méthodes de M."
Le compilateur traite la référence comme M. l'instance que les points de référence sont de type k, pas M. Vous ne pouvez pas lancer la référence et supposer que signifie l'instance va soudainement changer de comportement. Ce que le compilateur est assuré que la méthode que vous invoquez sur la référence spécifiée existe. Il n'a rien à voir avec quelle mise en œuvre est invoquée, seulement qu'une implémentation existe.


0 commentaires

0
votes

Casting d'un objet ne change pas l'objet à l'objet à la distribution, mais permet une autre référence de classe qui lui est liée par héritage pour se reporter à l'objet.

par exemple c étend e . Et ils ont tous les deux une méthode myName (); . Si vous dites xxx

Vous appelez C myName () méthode et si vous dites également xxx

Vous venez de dire au compilateur qu'il vous permettait de vous référer à E avec c type de référence.


0 commentaires