java - What's wrong with overridable method calls in constructors? -
i have wicket page class sets page title depending on result of abstract method.
public abstract class basicpage extends webpage { public basicpage() { add(new label("title", gettitle())); } protected abstract string gettitle(); }
netbeans warns me message "overridable method call in constructor", should wrong it? alternative can imagine pass results of otherwise abstract methods super constructor in subclasses. hard read many parameters.
on invoking overridable method constructors
simply put, wrong because unnecessarily opens possibilities many bugs. when @override
invoked, state of object may inconsistent and/or incomplete.
a quote effective java 2nd edition, item 17: design , document inheritance, or else prohibit it:
there few more restrictions class must obey allow inheritance. constructors must not invoke overridable methods, directly or indirectly. if violate rule, program failure result. superclass constructor runs before subclass constructor, overriding method in subclass invoked before subclass constructor has run. if overriding method depends on initialization performed subclass constructor, method not behave expected.
here's example illustrate:
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" } }
here, when base
constructor calls overrideme
, child
has not finished initializing final int x
, , method gets wrong value. lead bugs , errors.
related questions
- calling overridden method parent-class constructor
- state of derived class object when base class constructor calls overridden method in java
- using abstract init() function in abstract class’s constructor
see also
on object construction many parameters
constructors many parameters can lead poor readability, , better alternatives exist.
here's quote effective java 2nd edition, item 2: consider builder pattern when faced many constructor parameters:
traditionally, programmers have used telescoping constructor pattern, in provide constructor required parameters, single optional parameters, third 2 optional parameters, , on...
the telescoping constructor pattern this:
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; } }
and can of following:
new telescope("x/1999"); new telescope("x/1999", 13); new telescope("x/1999", 13, true);
you can't, however, set name
, isadjustable
, , leaving levels
@ default. can provide more constructor overloads, number explode number of parameters grow, , may have multiple boolean
, int
arguments, make mess out of things.
as can see, isn't pleasant pattern write, , less pleasant use (what "true" mean here? what's 13?).
bloch recommends using builder pattern, allow write instead:
telescope telly = new telescope.builder("x/1999").setadjustable(true).build();
note parameters named, , can set them in order want, , can skip ones want keep @ default values. better telescoping constructors, when there's huge number of parameters belong many of same types.
see also
- wikipedia/builder pattern
- effective java 2nd edition, item 2: consider builder pattern when faced many constructor parameters (excerpt online)
Comments
Post a Comment