Type Conversion des objets polymorphes Java <Br /> La conversion de type d'objet mentionné ici fait référence à un objet avec une relation d'héritage, pas un objet de tout type. Lorsque vous lancez un objet qui n'a pas de relation d'héritage, le runtime Java lance une exception java.lang.classCastException.
Dans la chaîne d'héritage, nous appelons la conversion de la sous-classe à la classe parent "transformation ascendante" et la conversion de classe parent à la classe de la classe infantile "transformation vers le bas".
Plusieurs fois, nous définissons les variables comme le type de la classe parent, mais se référons à l'objet de la classe enfant. Lorsque le programme s'exécute, il utilise une liaison dynamique pour réaliser l'appel aux méthodes de sous-classe, c'est-à-dire le polymorphisme.
Cependant, parfois pour remplir les fonctions que certaines classes de parents n'ont pas, nous devons convertir les objets de sous-classe transformés vers le haut en sous-classes et appeler les méthodes de sous-classe, qui est une transformation vers le bas.
Remarque: L'objet de la classe parent ne peut pas être jeté directement en un type de sous-classe, et l'objet de sous-classe après transformation ascendante ne peut être converti qu'à nouveau en type de sous-classe. En d'autres termes, les objets de sous-classe doivent être transformés vers le haut avant de pouvoir se transformer vers le bas. Veuillez consulter le code suivant:
classe publique Demo {public static void main (String args []) {superclass superObj = new superclass (); L'objet de classe est directement un type de sous-classe // sonclasse SONOBJ2 = (SONCLASS) SuperOBJ;Supprimez le commentaire sur la ligne 7, et une exception sera lancée au moment de l'exécution, mais la compilation peut être transmise.
Parce qu'il y a des risques dans la transition vers le bas, lorsque vous recevez une référence à la classe parent, assurez-vous d'utiliser l'opérateur d'instance pour déterminer si l'objet est la sous-classe que vous souhaitez.
classe publique Demo {public static void main (String args []) {superclass superObj = new superclass (); = (SonClass) SuperOBJ;} else {System.out.println ("① ne peut pas convertir"); ) superoBj;} else {System.out.println ("② ne peut pas être converti"); Résultats en cours:
① ne peut pas se convertir
Résumé: La conversion de type d'un objet est vérifiée lorsque le programme est exécuté.
Polymorphisme Java et liaison dynamique <Br /> En Java, les variables de la classe parent peuvent se référer aux instances de la classe parent ou des instances de la classe enfant.
Veuillez d'abord lire un morceau de code:
classe publique Demo {public statique vide (String [] args) {animal obj = nouveau animal (); .Cry ();}} classe Animal {// L'appel des animaux public Void Cry () {System.out.println ("Je ne sais pas comment appeler"); Call of Cat public void Cry () {System.out.println ("Meow ~");}} Class Dog étend Animal {// Dog Barking Public Void Cry () {System.out.println ("Wow ~"); }} Résultats en cours:
Je ne sais pas comment appeler le miaule ~ laine ~
Le code ci-dessus définit trois classes, à savoir les classes animales, chat et chien. La variable OBJ a un animal de type, qui peut pointer des cas de classe animale, ainsi que des cas de classes de chat et de chiens, ce qui est correct. C'est-à-dire que les variables de la classe parent peuvent se référer aux instances de la classe parent ou des instances de la classe infantile. Notez que l'inverse est mauvais, car tous les chats sont des animaux, mais tous les animaux ne sont pas des chats.
On peut voir que l'OBJ peut être un humain, un chat ou un chien. Le polymorphisme fait référence à une chose ayant des formes ou des formes différentes.
Par exemple, les «humains» ont également de nombreuses expressions ou implémentations différentes. , professeur ou médecin dans la prochaine vie.
Il existe trois conditions nécessaires pour que le polymorphisme existe: l'héritage, la réécriture et les variables parentales se réfèrent aux objets de sous-classe.
Lorsque vous appelez une méthode à l'aide d'une méthode polymorphe:
Vérifiez d'abord si la méthode est présente dans la classe parent.
Si la sous-classe remplace la méthode, la méthode de la sous-classe est appelée, sinon la méthode de classe parent est appelée.
Comme le montre l'exemple ci-dessus, un avantage du polymorphisme est que lorsqu'il existe de nombreuses sous-classes, il n'est pas nécessaire de définir plusieurs variables. Veuillez regarder l'exemple suivant:
classe publique Demo {public static void main (String [] args) {// avec l'aide du polymorphisme, le propriétaire peut nourrir de nombreux animaux maître ma = new maître (); ); ) {System.out.println ("Je suis un petit animal, mangeant" + f.getFood ()); Un petit chat mange "+ f.getFood ());}} le chien de classe étend l'animal {public void Eat (nourriture f) {System.out.println (" Je suis un chien, mange "+ f. GetFood ()) ; String getFood () {return "Bone";}} // maître classe maître {Public Void Feed (Animal F) {an.eat (f); Résultats en cours:
Je suis un petit animal, mange des choses, je suis un petit chat, je mange du poisson, je suis un chien, je mange des os
La méthode d'alimentation de la classe maître a deux paramètres, à savoir le type d'animal et le type de nourriture. différents animaux.
Liaison dynamique
Afin de comprendre la nature du polymorphisme, parlons du processus détaillé des méthodes d'appel Java ci-dessous.
1) Le compilateur vérifie le type de déclaration et le nom de la méthode de l'objet.
Supposons que Obj.func (param) soit appelé, OBJ est un objet de la classe CAT. Il convient de noter qu'il peut y avoir plusieurs méthodes avec des noms avec FUNC mais différents paramètres. Par exemple, les méthodes Func (INT) et Func (String) peuvent exister. Le compilateur répertorie toutes les méthodes nommées FUNC dans la classe CAT et les méthodes accédant à l'attribut public et nommé func dans son animal de classe parent.
De cette façon, le compilateur obtient une liste de toutes les méthodes de candidats possibles à appeler.
2) Ensuite, l'éditeur vérifiera la signature du paramètre fournie lors de l'appel de la méthode.
S'il existe une méthode dans toutes les méthodes nommées FUNC qui correspond exactement à la signature du paramètre fournie, sélectionnez cette méthode. Ce processus est appelé résolution de surcharge. Par exemple, si Func ("Hello") est appelé, le compilateur sélectionnera Func (String) au lieu de Func (int). En raison de l'existence de la conversion de type automatique, par exemple, INT peut être converti en double. fin ou plusieurs méthodes correspondent, puis compilez l'erreur.
De cette façon, le compilateur obtient le nom de la méthode et la signature du paramètre qui doit être appelé.
3) Si le modificateur de méthode est privé, statique, final (statique et final sera expliqué plus tard) ou un constructeur, le compilateur sera en mesure de savoir exactement quelle méthode devrait être appelée. .
En conséquence, la méthode appelée dépend du type réel de l'objet et implémente la liaison dynamique au moment de l'exécution. Par exemple, lors de l'appel de Func ("Hello"), l'éditeur utilisera la liaison dynamique pour générer une directive qui appelle Func (String).
4) Lorsque le programme s'exécute et utilise la liaison dynamique pour appeler la méthode, le JVM appellera certainement la méthode de la classe qui convient le plus au type réel de l'objet référencé par OBJ. Nous avons supposé que le type réel d'OBJ est Cat, qui est une sous-classe d'animaux, et il s'appelle si Func (String) est défini dans CAT, sinon il sera recherché dans la classe animale et sa classe parent.
Chaque appel à la méthode nécessite la recherche, ce qui est assez cher. De cette façon, lorsque la méthode est réellement appelée, la machine virtuelle ne peut que rechercher ce tableau. Dans l'exemple ci-dessus, le JVM recherche le tableau de la méthode de la classe CAT pour trouver une méthode qui correspond à l'appel à Func ("Hello"). Cette méthode peut être Cat.func (String) ou Animal.func (String). Notez que si super.func ("bonjour") est appelé, le compilateur recherchera la table de méthode de la classe parent.
En supposant que la classe animale contient trois méthodes: cry (), getName () et getage (), alors son tableau de méthode est le suivant:
cry () -> animal.cry ()
getName () -> animal.getName ()
getage () -> animal.getage ()
En fait, Animal a également un objet de classe parent par défaut (qui sera expliqué plus loin), qui héritera de la méthode de l'objet, de sorte que les méthodes énumérées ci-dessus ne sont pas complètes.
En supposant que la classe CAT remplace la méthode Cry () dans la classe animale et ajoute une nouvelle méthode Climbtree (), sa liste de paramètres est:
cry () -> cat.cry ()
getName () -> animal.getName ()
getage () -> animal.getage ()
Climbtree () -> Cat.Climbtree ()
Lors de l'exécution, le processus d'appel de la méthode obj.cry () est le suivant:
Le JVM accède d'abord au tableau de méthode du type réel d'OBJ, qui peut être le tableau de la méthode de la classe animale, ou le tableau de méthode de la classe CAT et de ses sous-classes.
JVM recherche une méthode correspondant à Cry () dans le tableau de la méthode, et après l'avoir trouvée, vous saurez à quelle classe il appartient.
Le JVM appelle cette méthode.