Sur l'appel du substituables méthode de constructeurs
Simplement, c'est faux, car il inutilement ouvre des possibilités à de NOMBREUX bugs. Lorsque l' @Override
est invoquée, l'état de l'objet peut être incohérente et/ou incomplètes.
Une citation de Efficace Java 2nd Edition, Point 17: Conception et document pour l'héritage, ou bien de l'interdire:
Il y a un peu plus de restrictions qu'une classe doit respecter pour permettre à l'héritage. Les constructeurs ne doivent pas invoquer des méthodes substituables, directement ou indirectement. Si vous ne respectez pas cette règle, le programme de l'échec entraîne. Le constructeur de la superclasse s'exécute avant le constructeur de sous-classe, de sorte que la méthode de remplacement dans la sous-classe d'être invoqués devant la sous-classe constructeur a été exécuté. Si la méthode de remplacement dépend de l'initialisation effectuée par le constructeur de sous-classe, la méthode ne fonctionnera pas comme prévu.
Voici un exemple pour illustrer:
public class ConstructorCallsOverride {
public static void main(String[] args) {
abstract class Base {
Base() { overrideMe(); }
abstract void overrideMe();
}
class Child extends Base {
final int x;
Child(int x) { this.x = x; }
@Override void overrideMe() {
System.out.println(x);
}
}
new Child(42); // prints "0"
}
}
Ici, lors de l' Base
constructeur appelle overrideMe
, Child
n'a pas terminé l'initialisation de l' final int x
, et la méthode renvoie la valeur faux. Ce sera presque certainement entraîner des bugs et erreurs.
Questions connexes
Voir aussi
Sur la construction de l'objet avec de nombreux paramètres
Les constructeurs avec de nombreux paramètres peuvent conduire à une mauvaise lisibilité, et de meilleures alternatives existent.
Voici une citation de Efficace Java 2nd Edition, Article 2: Considérons un générateur de modèle lorsqu'ils sont confrontés à de nombreux paramètres du constructeur:
Traditionnellement, les programmeurs ont utilisé le télescopage constructeur modèle, dans lequel vous fournir un constructeur avec uniquement les paramètres requis, l'autre avec un seul des paramètres optionnels, un troisième avec deux paramètres facultatifs, et ainsi de suite...
Le télescopage constructeur modèle est essentiellement quelque chose comme ceci:
public class Telescope {
final String name;
final int levels;
final boolean isAdjustable;
public Telescope(String name) {
this(name, 5);
}
public Telescope(String name, int levels) {
this(name, levels, false);
}
public Telescope(String name, int levels, boolean isAdjustable) {
this.name = name;
this.levels = levels;
this.isAdjustable = isAdjustable;
}
}
Et maintenant, vous pouvez effectuer les opérations suivantes:
new Telescope("X/1999");
new Telescope("X/1999", 13);
new Telescope("X/1999", 13, true);
Vous ne pouvez pas, cependant, actuellement seulement l' name
et isAdjustable
, et de quitter levels
en cas de défaut. Vous pouvez fournir plus de surcharges de constructeur, mais il est évident que le nombre pourrait exploser alors que le nombre de paramètres de croître, et vous pouvez même avoir plusieurs boolean
et int
arguments, ce qui serait vraiment faire un gâchis de choses.
Comme vous pouvez le voir, ce n'est pas agréable de modèle à écrire, et encore moins agréable à utiliser (Ce qui n'est "vrai"? Ce qui est de 13 ans?).
Bloch recommande l'utilisation d'un générateur de modèle, ce qui vous permettra d'écrire quelque chose comme ceci à la place:
Telescope telly = new Telescope.Builder("X/1999").setAdjustable(true).build();
Notez que les paramètres sont nommés, et vous pouvez les mettre dans l'ordre que vous voulez, et vous pouvez ignorer ceux que vous souhaitez conserver à des valeurs par défaut. C'est certainement beaucoup mieux que le télescopage les constructeurs, surtout quand il y a un grand nombre de paramètres qui appartiennent à un grand nombre des mêmes types.
Voir aussi
Questions connexes