You shouldn't call overridable methods from constructor.
In my
last Blog
I demonstrated how this can lead to unexpected results due to uninitialized instance fields.
In this Blog I want to show a way to circumvent this problem, without giving up the
protected abstract
initialization call to be implemented by sub-classes.
Replace constructor()
by init()
The first step is to move the logic done in constructor to a protected init()
instance-method.
This init()
is meant to be called by a static factory.
To avoid the usage of (implicitly public
) constructors from outside
we define them all as protected
, so that they can be called by
their own class and sub-classes only.
Here is the rewritten Name
class:
The init()
method now does what the constructor did before.
The constructor is now proctected
.
Add Static Factory
The rewritten concrete FirstName
class provides the static factory.
(This is NOT the "Factory Method" design pattern!)
The public static newFirstName()
is the factory.
It calls the init()
method after construction,
so that all sub-classes must have finished their field-initializations.
If you put all initializations inside that, there will be no problem any more with undefined fields.
When a factory is present, construction should not be possible from outside, thus all involved constructors
must be protected
or private
.
Mind the implementation order: statics first, then instance fields and methods.
The bad news is that you have to repeat the static factory code on any concrete sub-class, e.g. LastName
.
Test It
But before we think about that code duplication, let's test the new solution.
Now the factory is used to create the FirstName
object instance.
The assertion makes sure that the default is estimated correctly.
When compiling the sources with
tsc -t ES6 *.ts
and running the test (in the test.html
page I introduced in a
passed Blog),
we can see:
Call Overridables From Factory
firstName.getValue() is expected to be '(No Firstname)': '(No Firstname)'
Now the test is green!
Conclusion
Use a static factory whenever you need overrides already at construction time.
Is it possible to avoid the code duplication of the static factory? Maybe by using generics? There is even more code duplication, because both the factory and the init() method take over constructor responsibilities, therefore all construction parameters may have to be duplicated to both of them. Material for my next Blog.
Keine Kommentare:
Kommentar veröffentlichen