47 votes

Classe abstraite avec champ final non initialisé

Je me demandais si le code ci-dessous avait un sens, car le compilateur avertit que "les objets de champ final vierges n'ont peut-être pas été initialisés". Existe-t-il une meilleure façon de le faire?

 public abstract Test {
  protected final ArrayList<Object> objects;
}

public TestSubA extends Test {

  public TestSubA() {
    objects = new ArrayList<Objects>(20);
    // Other stuff
  }
}

public TestSubB extends Test {

  public TestSubB() {
    objects = new ArrayList<Objects>(100);
    // Other stuff
  }
}
 

43voto

Jon Skeet Points 692016

Je voudrais rendre le champ final et forcer les constructeurs à passer la valeur:

 public abstract class Test {
  private final ArrayList<Object> objects;

  protected ArrayList<Object> getObjects() {
    return objects;
  }

  protected Test(ArrayList<Object> objects) {
    this.objects = objects;
  }
}

public class TestSubA extends Test {

  public TestSubA() {
    super(new ArrayList<Object>(20));
    // Other stuff
  }
}

public class TestSubB extends Test {

  public TestSubB() {
    super(new ArrayList<Object>(100));
    // Other stuff
  }
}
 

5voto

qwertzguy Points 1021

Le problème avec l'initialisation des paramètres finaux directement dans le constructeur des sous-classes est que vous devez tout faire sur une seule ligne car super () doit être la première instruction du constructeur. Donc, à la place, je préfère rendre le constructeur privé et créer une méthode de construction statique comme celle-ci:

 public abstract class Test {
  private final ArrayList<Object> objects;

  protected ArrayList<Object> getObjects() {
    return objects;
  }

  protected Test(ArrayList<Object> objects) {
    this.objects = objects;
  }
}

public class TestSubA extends Test {
  public static TestSubA build() {
    ArrayList<Object> objects = new new ArrayList<Object>(20);
    objects.put(...);
    // Other stuff
    return new TestSubA(objects);
  }

  private TestSubA(ArrayList<Object> objects) {
    super(objects);
  }
}
 

2voto

ctrlShiftBryan Points 5620

Instanciez les objets dans le constructeur de classe abstraite et passez simplement la différence au constructeur.

0voto

Uri Points 50687

De manière générale, il peut être préférable d'avoir un constructeur dans la classe de base qui définit toujours le champ, et de ne pas avoir de constructeur par défaut qui ne le définit pas. Les sous-classes peuvent ensuite passer explicitement le paramètre dans la première ligne de leur constructeur en utilisant super (valeur)

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