158 votes

Constructeur dans une interface ?

Je sais qu'il n'est pas possible de définir un constructeur dans une interface. Mais je me demande pourquoi, car je pense que cela pourrait être très utile.

Ainsi, vous pouvez être sûr que certains champs d'une classe sont définis pour chaque implémentation de cette interface.

Considérons par exemple la classe de messages suivante :

public class MyMessage {

   public MyMessage(String receiver) {
      this.receiver = receiver;
   }

   private String receiver;

   public void send() {
      //some implementation for sending the mssage to the receiver
   }
}

Si je définis une interface pour cette classe afin d'avoir d'autres classes qui mettent en œuvre l'interface de message, je ne peux définir que la méthode d'envoi et non le constructeur. Comment puis-je donc m'assurer que chaque implémentation de cette classe possède réellement un ensemble de récepteurs ? Si j'utilise une méthode comme setReceiver(String receiver) Je ne peux pas être sûr que cette méthode soit réellement appelée. Dans le constructeur, je pourrais m'en assurer.

131voto

matt b Points 73770

En prenant certaines des choses que vous avez décrites :

"Ainsi vous pouvez être sûr que certains champs d'une classe sont définis pour chaque implémentation de cette interface."

"Si une interface est définie pour cette classe, je pourrai avoir d'autres classes classes qui implémentent l'interface message, je peux seulement définir la méthode méthode d'envoi et non le constructeur"

...ces exigences sont exactement ce que classes abstraites sont pour.

81voto

daniel kullmann Points 2619

Un problème que l'on rencontre lorsqu'on autorise les constructeurs dans les interfaces vient de la possibilité d'implémenter plusieurs interfaces en même temps. Lorsqu'une classe implémente plusieurs interfaces qui définissent des constructeurs différents, la classe devra implémenter plusieurs constructeurs, chacun ne satisfaisant qu'une interface, mais pas les autres. Il sera impossible de construire un objet qui appelle chacun de ces constructeurs.

Ou en code :

interface Named { Named(String name); }
interface HasList { HasList(List list); }

class A implements Named, HasList {

  /** implements Named constructor.
   * This constructor should not be used from outside, 
   * because List parameter is missing
   */
  public A(String name)  { 
    ...
  }

  /** implements HasList constructor.
   * This constructor should not be used from outside, 
   * because String parameter is missing
   */
  public A(List list) {
    ...
  }

  /** This is the constructor that we would actually 
   * need to satisfy both interfaces at the same time
   */ 
  public A(String name, List list) {
    this(name);
    // the next line is illegal; you can only call one other super constructor
    this(list); 
  }
}

12voto

rsp Points 14367

Une interface définit un contrat pour une API, c'est-à-dire un ensemble de méthodes sur lesquelles l'implémenteur et l'utilisateur de l'API s'accordent. Une interface n'a pas d'implémentation instanciée, donc pas de constructeur.

Le cas d'utilisation que vous décrivez s'apparente à une classe abstraite dans laquelle le constructeur appelle une méthode d'une méthode abstraite qui est mise en œuvre dans une classe enfant.

Le problème inhérent ici est que pendant que le constructeur de base est exécuté, l'objet enfant n'est pas encore construit, et donc dans un état imprévisible.

Pour résumer, est-ce qu'on risque d'avoir des problèmes quand on appelle des méthodes surchargées à partir de constructeurs parents, pour citer mindprod :

En général, vous devez éviter d'appeler tout méthodes non finales dans un constructeur. Le problème est que l'instance initialisation des instances / initialisation des variables dans la classe dérivée sont effectuées après le constructeur de la base de base.

6voto

Lappro Points 113

Une solution que vous pouvez essayer est de définir un getInstance() dans votre interface afin que l'implémenteur sache quels paramètres doivent être gérés. Ce n'est pas aussi solide qu'une classe abstraite, mais cela permet plus de flexibilité qu'une interface.

Toutefois, cette solution de contournement nécessite l'utilisation de l'option getInstance() pour instancier tous les objets de cette interface.

Par exemple

public interface Module {
    Module getInstance(Receiver receiver);
}

4voto

Satyajit Gami Points 51

Il n'y a que des champs statiques dans l'interface qui n'ont pas besoin d'être initialisés pendant la création de l'objet dans la sous-classe et la méthode de l'interface doit fournir l'implémentation réelle dans la sous-classe, donc il n'y a pas besoin de constructeur dans l'interface.

Deuxième raison : lors de la création d'un objet d'une sous-classe, le constructeur parent est appelé, mais s'il y a plus d'une interface implémentée, un conflit se produira lors de l'appel du constructeur de l'interface pour savoir lequel des constructeurs de l'interface sera appelé en premier.

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