106 votes

Pourquoi assigne-t-on une référence parentale à l'objet enfant en Java ?

Je pose une question assez simple, mais je suis un peu confus.

Supposons que j'ai une classe Parent :

public class Parent {

    int name;
}

Et avoir une autre classe Child :

public class Child extends Parent{

    int salary;
}

Et enfin ma classe Main.java

public class Main {

    public static void main(String[] args)
    {
        Parent parent = new Child();
        parent.name= "abcd";
    }
}

Si je crée un objet enfant comme

Child child = new Child():

Puis child peut accéder aux deux name and salary variables.

Ma question est la suivante :

Parent parent = new Child();

donne l'accès de seulement name de la classe Parent. Quelle est donc l'utilité exacte de cette ligne ?

 Parent parent = new Child();

Et aussi quand on utilise le polymorphisme dynamique, pourquoi la variable de la classe enfant n'est pas accessible après avoir fait cela ?

Parent parent = new Child();

3voto

Swapneil Points 31

Je sais que c'est un très vieux fil de discussion mais j'ai rencontré le même doute une fois.

Donc le concept de Parent parent = new Child(); a quelque chose à voir avec les liaisons précoces et tardives en Java.

La liaison des méthodes privées, statiques et finales se fait à la compilation car elles ne peuvent pas être surchargées. Les appels normaux de méthodes et les méthodes surchargées sont des exemples de liaison précoce.

Prenons un exemple :

class Vehicle
{
    int value = 100;
    void start() {
        System.out.println("Vehicle Started");
    }

    static void stop() {
        System.out.println("Vehicle Stopped");
    }
}

class Car extends Vehicle {

    int value = 1000;

    @Override
    void start() {
        System.out.println("Car Started");
    }

    static void stop() {
        System.out.println("Car Stopped");
    }

    public static void main(String args[]) {

        // Car extends Vehicle
        Vehicle vehicle = new Car();
        System.out.println(vehicle.value);
        vehicle.start();
        vehicle.stop();
    }
}

Sortie : 100

La voiture a démarré

Véhicule arrêté

Cela se produit parce que stop() est une méthode statique et ne peut pas être surchargée. Ainsi, la liaison de stop() se produit au moment de la compilation et start() qui n'est pas statique est surchargée dans la classe enfant. Ainsi, l'information sur le type d'objet n'est disponible qu'au moment de l'exécution (liaison tardive) et, par conséquent, l'information sur le type d'objet n'est pas disponible. start() de la classe Car est appelée.

Dans ce code également, le vehicle.value nous donne 100 en tant que sortie, car l'initialisation des variables ne fait pas partie des liaisons tardives. La substitution de méthode est l'un des moyens par lesquels Java prend en charge le polymorphisme au moment de l'exécution. .

  • Lorsqu'une méthode surchargée est appelée par une référence à une superclasse, Java détermine la version (superclasse/sous-classe) de cette méthode à exécuter en fonction du type de l'objet auquel il est fait référence au moment de l'appel. Ainsi, cette détermination est effectuée au moment de l'exécution.
  • Au moment de l'exécution, c'est le type de l'objet auquel il est fait référence (et non le type de la variable de référence) qui détermine quelle version d'une méthode surchargée sera exécutée.

J'espère que cela répond aux questions où Parent parent = new Child(); est important et aussi pourquoi vous n'avez pas pu accéder à la variable de la classe enfant en utilisant la référence ci-dessus.

2voto

FrancescoAzzola Points 2039

Cette situation se produit lorsque vous avez plusieurs implémentations. Je m'explique. Supposons que vous ayez plusieurs algorithmes de tri et que vous vouliez choisir à l'exécution celui à implémenter, ou que vous vouliez donner à quelqu'un d'autre la possibilité d'ajouter son implémentation. Pour résoudre ce problème, vous créez généralement une classe abstraite (Parent) et vous avez différentes implémentations (Child). Si vous écrivez :

Child c = new Child();

vous liez votre implémentation à la classe Enfant et vous ne pouvez plus la modifier. Sinon, si vous utilisez :

Parent p = new Child();

tant que Child étend Parent, vous pouvez le changer à l'avenir sans modifier le code.

La même chose peut être faite en utilisant des interfaces : Parent n'est plus une classe mais une interface java.

En général, vous pouvez utiliser cette approche dans le modèle DAO lorsque vous souhaitez avoir plusieurs implémentations dépendantes de la base de données. Vous pouvez jeter un coup d'oeil au FactoryPatter ou au AbstractFactory Pattern. J'espère que cela pourra vous aider.

1voto

soliloquyy Points 353

Disons que vous aimeriez avoir un tableau d'instances de la classe Parent, et un ensemble de classes enfants Child1, Child2, Child3 étendant Parent. Dans certaines situations, vous n'êtes intéressé que par l'implémentation de la classe parent, qui est plus générale, et vous ne vous souciez pas des éléments suivants des choses plus spécifiques introduit par les classes enfantines.

1voto

George Smith Points 161

Je pense que toutes les explications ci-dessus sont un peu trop techniques pour les personnes qui découvrent la programmation orientée objet (POO). Il y a quelques années, il m'a fallu un certain temps pour m'y retrouver (en tant que développeur Java junior) et je ne comprenais vraiment pas pourquoi nous utilisons une classe parente ou une interface pour cacher la classe que nous appelons réellement sous la couverture.

  1. La raison immédiate est de cacher la complexité, de sorte que l'appelant n'ait pas besoin de changer souvent (être hacké et jacké en termes profanes). Cela a beaucoup de sens, surtout si votre objectif est d'éviter de créer des bogues. Et plus vous modifiez le code, plus il est probable que certains d'entre eux se glissent dans votre esprit. D'un autre côté, si vous vous contentez d'étendre le code, il est beaucoup moins probable que vous ayez des bogues, car vous vous concentrez sur une seule chose à la fois et votre ancien code ne change pas ou peu. Imaginez que vous avez une application simple qui permet aux employés du corps médical de créer des profils. Pour simplifier, supposons que nous n'ayons que des médecins généralistes, des chirurgiens et des infirmières (en réalité, il y a bien sûr beaucoup plus de professions spécifiques). Pour chaque profession, vous souhaitez stocker des informations générales et d'autres spécifiques à cette seule profession. Par exemple, un chirurgien peut avoir des champs généraux comme Prénom, Nom, Années d'expérience, mais aussi des champs spécifiques, par exemple des spécialisations stockées dans une variable d'instance de type liste, avec des contenus similaires à "Chirurgie osseuse", "Chirurgie oculaire", etc. Une infirmière n'aurait rien de tout cela, mais pourrait avoir des procédures de liste avec lesquelles elle est familière, les chirurgiens généralistes auraient leurs propres spécificités. Par conséquent, la façon dont vous enregistrez le profil d'un spécifique. Cependant, vous ne voulez pas que votre classe ProfileManager connaisse ces différences, car elles vont inévitablement changer et augmenter au fil du temps, à mesure que votre application étend ses fonctionnalités pour couvrir davantage de professions médicales, par exemple kinésithérapeute, cardiologue, oncologue, etc. Tout ce que vous voulez que votre ProfileManger fasse, c'est dire save(), quel que soit le profil qu'il enregistre. Ainsi, il est courant de cacher cela derrière une interface, une classe abstraite ou une classe mère (si vous prévoyez d'autoriser la création d'un employé médical général). Dans ce cas, choisissons une classe parent et appelons-la MedicalEmployee. Sous couvert, elle peut faire référence à n'importe laquelle des classes spécifiques ci-dessus qui l'étendent. Lorsque le ProfileManager appelle myMedicalEmployee.save(), la méthode save() sera résolue de manière polymorphe (multistructurelle) vers le type de classe correct qui a été utilisé pour créer le profil à l'origine, par exemple Nurse, et appellera la méthode save() dans cette classe.

  2. Dans de nombreux cas, vous ne savez pas vraiment de quelle implémentation vous aurez besoin au moment de l'exécution. Dans l'exemple ci-dessus, vous ne savez pas si un médecin généraliste, un chirurgien ou un infirmier créera un profil. Pourtant, vous savez que vous devez enregistrer ce profil une fois terminé, quoi qu'il arrive. MedicalEmployee.profile() fait exactement cela. Elle est répliquée (surchargée) par chaque type spécifique de MedicalEmployee - médecin généraliste, chirurgien, infirmier,

  3. Le résultat de (1) et (2) ci-dessus est que vous pouvez maintenant ajouter de nouvelles professions médicales, implémenter save() dans chaque nouvelle classe, en surchargeant ainsi la méthode save() dans MedicalEmployee, et vous ne devez pas modifier ProfileManager du tout.

-1voto

S G Points 9

Par exemple, nous avons un

class Employee

{

int getsalary()

{return 0;}

String getDesignation()

{

return “default”;

}

}

class Manager extends Employee

{

int getsalary()

{

return 20000;

}

String getDesignation()

{

return “Manager”

}

}

class SoftwareEngineer extends Employee

{

int getsalary()

{

return 20000;

}

String getDesignation()

{

return “Manager”

}

}

Maintenant, si vous voulez définir ou obtenir le salaire et la désignation de tous les employés (par exemple, ingénieur logiciel, directeur, etc.).

nous allons prendre un tableau d'employés et appeler les deux méthodes getsalary(),getDesignation

Employee arr[]=new Employee[10];

arr[1]=new SoftwareEngieneer();

arr[2]=new Manager();

arr[n]=…….

for(int i;i>arr.length;i++)

{

System.out.println(arr[i].getDesignation+””+arr[i].getSalary())

}

maintenant c'est une sorte de couplage lâche parce que vous pouvez avoir différents types d'employés ex : ingénieur logiciel, manager, hr, pantryEmployee etc

ainsi vous pouvez donner l'objet à la référence parentale indépendamment de l'objet employé différent

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X