web-dev-qa-db-fra.com

Passage d'objet superclasse en tant que paramètre du constructeur de sous-classe (Java)

J'ai fait quelques recherches, mais je ne pose pas la bonne question ou je ne me souviens pas correctement. Dans tous les cas, en Java, je me demande s’il est possible de passer l’objet de la super-classe en tant que paramètre à une sous-classe et quel est le moyen le plus efficace de rendre les données de cet objet disponibles pour la super-classe de la classe.

Exemples de code:

public class superclass {
  String myparm1;
  String myParm2;
  int myParmN;

  public superclass(String p1, String p2, int pn)
  {
    this.myparm1 = p1;
    this.myparm2 = p2;
    this.myParmN = pn;
  }
  // other methods here
}

public class subclass extends superclass {
  double b1;
  double b2;

  public subclass(superclass sc, double b1, double b2) {
    // easy way to make sc data available to this class?
    // Do I create a copy or clone method, or some other way?
    // calling super(sc); wouldn't exactly work 
    this.b1 = b1;
    this.b2 = b2;
  }
}

si j'avais un constructeur dans la super-classe qui était public superclass(superclass sc) { // assign sc properties to this properties, correct? }, je pourrais simplement utiliser super(sc);

7
Machtyn

Il est inutile de faire référence à la super-classe d'un objet dans le constructeur. Votre sous-classe est déjà une instance de la superclasse. 

Même si vous ne pouvez pas voir directement les composants privés de la super-classe, ils existent toujours et les appels aux méthodes d'accès public produisent toujours un comportement normal. 

En réponse à votre deuxième question, le moyen le plus efficace d'accéder aux données à l'intérieur de la classe parente consiste à utiliser les méthodes d'accès de cette classe parente. Si des méthodes get/set properties remplissent certaines structures de données, appelez-les simplement à partir de votre classe enfant et elles fonctionneront exactement de la même manière que pour le parent. Maintenant, si ces structures de données internes sont renseignées par le constructeur de la classe parente, vous devrez appeler ce constructeur avec les méthodes appropriées lorsque vous créez une instance du constructeur enfant qui en a besoin - généralement en appelant le super () approprié au début du constructeur de l'enfant. 

Si vous essayez de contourner la restriction selon laquelle vous ne pouvez pas voir les parties privées de la super-classe, Java ne vous le permet pas intentionnellement. Vous pouvez contourner cela avec réflexion sauf si vous êtes coincé dans un environnement d'exécution qui l'interdit, mais je ne considérerais généralement pas cela comme une approche sûre ou élégante. 

D'après les commentaires ci-dessous, je comprends ce que le PO essaie de faire et cela devrait fonctionner, bien que cela dépende évidemment de votre capacité à apporter des modifications à la super classe:

public class Super
{
    public Super (Super other)
    {
        //copy stuff from other to this
    }
}

public class Child extends Super
{
    public Child (Super other)
    {
        super(other);
        //continue constructor
    }

}
5
Jim W

Tu ne peux pas. Lorsque vous créez un objet avec Java (par exemple, avec new), cette instance a une classe et cette classe a un parent (éventuellement Object).

La relation parent-enfant ne concerne que les classes, pas les objets! Aucun objet n'a un objet parent (au moins, pas au niveau du langage) - vous ne pouvez donc pas accepter le parent dans le constructeur et le stocker dans un emplacement défini par Java.

Toutefois, votre domaine peut avoir des entités parent et enfant. Dans ce cas, vous avez besoin de champs ou de structures de données pour stocker les liens entre eux.

2
Raffaele

Pour répondre à une question précédente, supposons que la superclasse ait un grand nombre de propriétés. Dans ce cas, la conception de la classe peut être mauvaise, bien sûr.

Peut-être que la meilleure réponse est:

public class superclass {
  // properties and constructors as defined in OP

  public void copy(superclass sc) {
    this.myParm1 = sc.getMyParm1();
    this.myParm2 = sc.getMyParm2();
    this.myParmN = sc.getMyParmN();
  }

  // other methods as needed
}

De cette façon, la sous-classe peut simplement appeler la super.copy(sc). Bien sûr, il me faudrait un autre constructeur dans la superclasse qui définira les valeurs par défaut: public superclass() { // set defaults }

Donc, la sous-classe pourrait être:

public class subclass extends superclass {
  //properties as defined in OP

  public subclass(superclass sc, double b1, double b2) {
    this.b1 = b1;
    this.b2 = b2;
    super.copy(sc);
  }
}

De cette façon, je n'ai qu'à saisir ces paramètres et les sous-classes qui souhaitent accepter un objet de super-classe n'ont pas à définir cette structure à chaque fois. (moins de frappe, moins de chance d'erreur ou d'oublier quelque chose.)

0
Machtyn