web-dev-qa-db-fra.com

Quelle est la différence entre la conversion ascendante et descendante par rapport à la variable de classe

Quelle est la différence entre une transformation ascendante et une transformation descendante par rapport à la variable de classe?

Par exemple, dans la classe de programme suivante, Animal ne contient qu'une seule méthode, mais la classe Dog en contient deux, puis la conversion de la variable Dog en variable Animal.

Si le casting est terminé, comment pouvons-nous appeler la méthode du chien d'une autre méthode avec la variable de Animal.

class Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}


class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class UseAnimlas 
{
    public static void main (String [] args) 
    {
        Dog d = new Dog();      
        Animal a = (Animal)d;
        d.callme();
        a.callme();
        ((Dog) a).callme2();
    }
}
107
Dhivakar

La conversion ascendante correspond à un super-type, tandis que la conversion en aval est convertie à un sous-type. La conversion en amont est toujours autorisée, mais la conversion en aval implique une vérification de type et peut générer une variable ClassCastException.

Dans votre cas, une conversion d'une Dog à une Animal est un upcast, car une Dog est-une Animal. En général, vous pouvez effectuer une conversion ascendante chaque fois qu'il existe une relation is-a entre deux classes.

La descente serait quelque chose comme ceci:

Animal animal = new Dog();
Dog castedDog = (Dog) animal;

En gros, vous dites au compilateur que vous connaissez le type d'exécution de l'objet. vraiment est. Le compilateur autorisera la conversion, mais insérera tout de même un contrôle d'intégrité au moment de l'exécution afin de s'assurer que la conversion est logique. Dans ce cas, le transtypage est possible car, à l'exécution, animal est en fait un Dog même si le type statique de animal est Animal.

Cependant, si vous deviez le faire:

Animal animal = new Animal();
Dog notADog = (Dog) animal;

Vous obtiendrez une ClassCastException. La raison en est que le type d'exécution de animal est Animal. Ainsi, lorsque vous indiquez à l'exécution d'effectuer le transtypage, il voit que animal n'est pas vraiment un Dog et lance donc un ClassCastException.

Pour appeler la méthode d'une super-classe, vous pouvez utiliser super.method() ou en effectuant la conversion ascendante.

Pour appeler la méthode d'une sous-classe, vous devez effectuer un downcast. Comme indiqué ci-dessus, vous risquez normalement une ClassCastException en faisant cela; Cependant, vous pouvez utiliser l'opérateur instanceof pour vérifier le type d'exécution de l'objet avant d'effectuer la conversion, ce qui vous permet d'éviter les ClassCastExceptions:

Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
    // Guaranteed to succeed, barring classloader shenanigans
    Dog castedDog = (Dog) animal;
}
166
awksp

Down-casting et up-casting était comme suit:
 enter image description here

Upcasting: lorsque nous voulons convertir une sous-classe en super classe, nous utilisons Upcasting (ou élargissement). Cela se produit automatiquement, pas besoin de faire quoi que ce soit explicitement. 

Downcasting: lorsque nous souhaitons convertir une classe Super en classe Sub, nous utilisons Downcasting (ou rétrécissement), et le Downcasting n'est pas directement possible en Java, nous devons le faire explicitement. 

Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException
44
Premraj

La conversion ascendante et descendante est une partie importante de Java, qui nous permet de construire des programmes compliqués en utilisant une syntaxe simple et nous donne de grands avantages, comme le polymorphisme ou le regroupement de différents objets.Java permet à un objet d'un type de sous-classe d'être traité comme un objet de n'importe quel type de superclasse. Ceci s'appelle upcasting. La conversion en amont est effectuée automatiquement, alors que la conversion en descente doit être effectuée manuellement par le programmeur, et je vais faire de mon mieux pour expliquer pourquoi il en est ainsi.

La conversion ascendante et descendante ne ressemble PAS à la transposition de primitives les unes par les autres, et j'estime que c'est ce qui cause beaucoup de confusion lorsque le programmeur commence à apprendre le transtypage d'objets.

Polymorphisme: toutes les méthodes en Java sont virtuelles par défaut. Cela signifie que n'importe quelle méthode peut être remplacée lorsqu'elle est utilisée dans un héritage, à moins que cette méthode soit déclarée comme finale ou static.

Vous pouvez voir l'exemple ci-dessous comment getType(); fonctionne en fonction du type d'objet (chien, animal domestique, chien policier).

Supposons que vous avez trois chiens 

  1. Chien - C'est la classe super.
  2. Pet Dog - Pet Dog étend le chien.
  3. Chien policier - Chien policier étend son chien. 

    public class Dog{ 
       public String getType () {
          System.out.println("NormalDog");
          return "NormalDog";
       }
     }
    
    /**
     * Pet Dog has an extra method dogName()
     */   
    public class PetDog extends Dog{ 
       public String getType () {
          System.out.println("PetDog");
          return "PetDog";
       }
       public String dogName () {
          System.out.println("I don't have Name !!");
          return "NO Name";
       }
     }
    
    /**
     * Police Dog has an extra method secretId()
     */
    public class PoliceDog extends PetDog{
    
     public String secretId() {
        System.out.println("ID");
        return "ID";
     }
    
     public String getType () {
         System.out.println("I am a Police Dog");
         return "Police Dog";
     }
    }
    

Polymorphisme: Toutes les méthodes en Java sont virtuelles par défaut. Cela signifie que n'importe quelle méthode peut être remplacée lorsqu'elle est utilisée dans un héritage, à moins que cette méthode ne soit déclarée comme finale ou statique. (Explication, appartient au concept de tables virtuelles)

Table virtuelle/table de répartition: La table de répartition d'un objet contient les adresses des méthodes liées de manière dynamique. Les appels de méthode sont effectués en extrayant l'adresse de la méthode à partir de la table de répartition de l'objet. La table de répartition est la même pour tous les objets appartenant à la même classe et est donc généralement partagée entre eux.

public static void main (String[] args) {
      /**
       * Creating the different objects with super class Reference
       */
     Dog obj1 = new Dog();
`         /**
           *  Object of Pet Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry about it 
           *  
           */
     Dog obj2 = new PetDog();
`         /**
           *  Object of Police Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry       
           *  about it here even though we are extending PoliceDog with PetDog 
           *  since PetDog is extending Dog Java automatically upcast for us 
           */
      Dog obj3 = new PoliceDog();
}



 obj1.getType();

Imprime Normal Dog 

  obj2.getType();

Imprime Pet Dog

 obj3.getType();

Imprime Police Dog

Le programmeur doit procéder manuellement au downcasting  

Lorsque vous essayez d'appeler la méthode secretID(); sur obj3 qui est PoliceDog object mais référencée à Dog qui est une super classe dans la hiérarchie, une erreur est générée car obj3 n'a pas accès à la méthode secretId().Pour invoquer cette méthode, vous besoin de Downcast manuellement cet obj3 enPoliceDog

  ( (PoliceDog)obj3).secretID();

qui imprime ID

De la même manière pour invoquer la méthode dogName(); dans la classe PetDog, vous devez rétrograder obj2 en PetDog puisque obj2 est référencé à Dog et que vous n'avez pas accès à la méthode dogName();.

  ( (PetDog)obj2).dogName();

Pourquoi est-ce vrai? Le upcasting est automatique, mais le downcasting doit être manuel. Eh bien, voyez-vous, la surchauffe ne peut jamais échouer. Mais si vous avez un groupe de chiens différents et que vous voulez les réduire à leurs types, il est alors possible que certains de ces chiens soient réellement de types différents, par exemple, PetDog, PoliceDog et le processus échoue, par jeter ClassCastException.

C’est la raison pour laquelle vous devezdécaler vos objets manuellementsi vous avez référencé vos objets au type de super classe.

Remarque: ici, en faisant référence, vous ne modifiez pas l'adresse mémoire de vos objets lorsque vous les descendez, mais vous ne les groupez que dans un type particulier dans ce cas Dog

27
Nagarjuna Yelisetty

Je sais que cette question a été posée il y a assez longtemps, mais pour les nouveaux utilisateurs de cette question . S'il vous plaît lire cet article où contient une description complète sur la conversion ascendante, downcasting et l'utilisation de l'opérateur instanceof 

  • Il n'est pas nécessaire d'effectuer une surchauffe manuellement, cela se produit tout seul:

    Mammal m = (Mammal)new Cat(); est égal à Mammal m = new Cat();

  • Mais le downcasting doit toujours être fait manuellement:

    Cat c1 = new Cat();      
    Animal a = c1;      //automatic upcasting to Animal
    Cat c2 = (Cat) a;    //manual downcasting back to a Cat
    

Pourquoi est-ce vrai? Le upcasting est automatique, mais le downcasting doit être manuel. Eh bien, voyez-vous, la surchauffe ne peut jamais échouer. Mais si vous avez un groupe d’Animaux différents et que vous voulez tous les abattre en un chat, il est alors possible que certains de ces animaux soient en fait des chiens et que le processus échoue en lançant ClassCastException . C’est là où il faut introduire. une fonctionnalité utile appelée "instanceof", qui teste si un objet est une instance de Class.

 Cat c1 = new Cat();         
    Animal a = c1;       //upcasting to Animal
    if(a instanceof Cat){ // testing if the Animal is a Cat
        System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");        
        Cat c2 = (Cat)a;
    }

Pour plus d'informations, veuillez lire cet article

12

Mieux vaut essayer cette méthode pour le upcasting, il est facile à comprendre:

/* upcasting problem */
class Animal
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}

class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class Useanimlas 
{
    public static void main (String [] args) 
    {
        Animal animal = new Animal ();
        Dog dog = new Dog();
        Animal ref;
        ref = animal;
        ref.callme();
        ref = dog;
        ref.callme();
    }
}
6
UWAIS

Peut-être que ce tableau est utile… Appeler la méthode callme() de la classe Parent ou de la classe Child. En principe:

UPCASTING -> Cacher

DOWNCASTING -> Révéler

enter image description here

enter image description here

enter image description here

5
Alexis

Parent: voiture
Enfant: Figo
Car c1 = nouveau Figo ();

=====
Upcasting: -
Méthode: L'objet c1 fera référence à Méthodes de classe (Figo - La méthode doit être remplacée) car la classe "Figo" est spécifiée avec "new".
Variable d'instance: L'objet c1 fera référence à la variable d'instance de la classe de déclaration ("Car"). 

Lorsque la classe de déclaration est un parent et qu'un objet est créé avec un enfant, un transtypage implicite se produit, à savoir "Upcasting". 

======
Downcasting: -
Figo f1 = (Figo) c1; //
Méthode: L'objet f1 fera référence à la méthode de la classe (figo) car l'objet initial c1 est créé avec la classe "Figo". mais une fois le down casting terminé, les méthodes qui ne sont présentes que dans la classe "Figo" peuvent également être appelées par la variable f1.
Variable d'instance: L'objet f1 ne fera pas référence à la variable d'instance de la classe de déclaration de l'objet c1 (la classe de déclaration pour c1 est CAR), mais en aval, il fera référence aux variables d'instance de la classe Figo. 

======
Utilisation: Lorsque Object a la classe enfant et que la classe de déclaration est parent et que la classe veut accéder à la variable d'instance de sa propre classe et non de la classe parent, vous pouvez le faire avec "Downcasting". 

2
amit shah

1.- Upcasting.

En effectuant une conversion en amont, vous définissez une balise d'un type quelconque qui pointe vers un objet d'un sous-type (le type et le sous-type peuvent être appelés classe et sous-classe, si vous vous sentez plus à l'aise ...).

Animal animalCat = new Cat();

Ce qui signifie qu'une telle balise, animalCat, aura la fonctionnalité (les méthodes) de type Animal uniquement, car nous l'avons déclarée comme type Animal, pas comme type Cat.

Nous sommes autorisés à le faire de manière "naturelle/implicite/automatique", lors de la compilation ou de l'exécution, principalement parce que Cat hérite de certaines de ses fonctionnalités d'Animal; Par exemple, move (). (Au moins, le chat est un animal, n'est-ce pas?)

2.- Downcasting.

Mais que se passerait-il si nous devions obtenir les fonctionnalités de Cat, à partir de notre type tag Animal?.

Comme nous avons créé la balise animalCat pointant sur un objet Cat, nous avons besoin d’un moyen d’appeler les méthodes de l’objet Cat à partir de notre balise animalCat de façon très élégante.

Une telle procédure est ce que nous appelons le Downcasting, et nous ne pouvons le faire qu'au moment de l'exécution.

Temps pour un code:

public class Animal {
    public String move() {
        return "Going to somewhere";
    }
}

public class Cat extends Animal{
    public String makeNoise() {
        return "Meow!";
    }   
}

public class Test {

    public static void main(String[] args) {

    //1.- Upcasting 
    //  __Type_____tag________object
        Animal animalCat = new Cat();
    //Some animal movement
        System.out.println(animalCat.move());
        //prints "Going to somewhere"

    //2.- Downcasting   
    //Now you wanna make some Animal noise.
        //First of all: type Animal hasn't any makeNoise() functionality.
        //But Cat can do it!. I wanna be an Animal Cat now!!

        //___________________Downcast__tag_____ Cat's method
        String animalNoise = ( (Cat) animalCat ).makeNoise();

        System.out.println(animalNoise);
        //Prints "Meow!", as cats usually done.

    //3.- An Animal may be a Cat, but a Dog or a Rhinoceros too.
        //All of them have their own noises and own functionalities.
        //Uncomment below and read the error in the console:

    //  __Type_____tag________object
        //Cat catAnimal = new Animal();

    }

}
2
Lemmy_Caution

upcasting signifie convertir l'objet en un super-type, tandis que le downcasting signifie attribuer à un sous-type.

En Java, la conversion en amont n'est pas nécessaire car elle est effectuée automatiquement. Et on parle généralement de casting implicite. Vous pouvez le spécifier pour le rendre clair aux autres.

Ainsi, écrire

Animal a = (Animal)d;

ou

Animal a = d;

conduit exactement au même point et dans les deux cas sera exécuté la callme() de Dog.

Le downcasting est plutôt nécessaire car vous avez défini a comme objet de Animal. Actuellement, vous savez que c'est une Dog, mais Java n'a aucune garantie que ce soit. En fait, au moment de l'exécution, cela pourrait être différent et Java lancera une ClassCastException, si cela se produisait. Bien sûr, ce n'est pas le cas de votre exemple même. Si vous ne transmettiez pas a à Animal, Java ne pourrait même pas compiler l'application car Animal ne dispose pas de la méthode callme2().

Dans votre exemple, vous ne pouvez pas atteindre le code callme() de Animal à partir de UseAnimlas (car Dog l'écraser) à moins que la méthode ne soit la suivante:

class Dog extends Animal 
{ 
    public void callme()
    {
        super.callme();
        System.out.println("In callme of Dog");
    }
    ... 
} 
1
David

Nous pouvons créer un objet à Downcasting. Dans ce type aussi. : appel des méthodes de classe de base 

Animal a=new Dog();
a.callme();
((Dog)a).callme2();
0
Rakesh