Reputation: 6256
Suppose I have :
class FooMom {
String momField1;
Integer momField2;
...
String momField10;
}
And a child class:
class Foo extends FooMom {
String extraField;
}
How can I refactor this code bellow
FooMom fooMom ;
if (someCondition) {
fooMom = new FooMom("momField1", ..., "momField10");
}
else {
fooMom = new Foo("momField1", ..., "momField10", "extraField");
}
I don't like the repetition of "momField1", ..., "momField10"
in the two constructors
Is there a way like
FooMom fooMom = new FooMom("momField1", ..., "momField10");
if (!someCondition) {
// adding the extraField to Foo instance
}
Upvotes: 0
Views: 95
Reputation: 2588
Multiple possibilities:
String[]
or String...
FooMom
and Foo
FooMom
first, and have something like a Copy-Constructor in Foo
: public Foo(FooMom original, String extraField) {...}
that copies the values of the original/passed objectFunction
s or Consumer
s) to the CTORs of the objects, this will reduce repitition but make the whole thing more verboseThis is IMO the most elegant solution, implementing suggestion #3:
public class ChainedCTORs_Example3 {
static class FooMom {
private final String momField1;
private final Integer momField2;
private final String momField10;
// public FooMom(final FooMom pOriginal) { // classical Copy-CTOR
// momField1 = pOriginal.momField1;
// momField2 = pOriginal.momField2;
// momField10 = pOriginal.momField10;
// }
public FooMom(final FooMom pOriginal) { // Alternative Copy-CTOR with CTOR Chaining, same effect
this(pOriginal.momField1, pOriginal.momField2, pOriginal.momField10);
}
public FooMom(final String pMomField1, final Integer pMomField2, final String pMomField10) {
momField1 = pMomField1;
momField2 = pMomField2;
momField10 = pMomField10;
}
}
static class Foo extends FooMom {
private final String extraField;
public Foo(final FooMom pFooMom, final String pExtraField) {
super(pFooMom);
extraField = pExtraField;
}
}
public static void main(final String[] args) {
final boolean someCondition = Math.random() < 0.5;
FooMom fooMom = new FooMom("momField1", Integer.valueOf(667), "momField10");
if (!someCondition) {
fooMom = new Foo(fooMom, "extraField");
}
}
}
Remark: I made those fields final
so initialization is guaranteed (in-code proof it works), and private
as default.
Example for suggestion #4:
import java.util.function.Supplier;
public class LambdaCtors_Example4 {
static class FooMom {
private final String momField1;
private final Integer momField2;
private final String momField10;
public FooMom(final Supplier<String> pS1, final Supplier<Integer> pS2, final Supplier<String> pS3) {
momField1 = pS1.get();
momField2 = pS2.get();
momField10 = pS3.get();
}
}
static class Foo extends FooMom {
private final String extraField;
public Foo(final Supplier<String> pS1, final Supplier<Integer> pS2, final Supplier<String> pS3, final Supplier<String> pS4) {
super(pS1, pS2, pS3);
extraField = pS4.get();
}
}
public static void main(final String[] args) {
final boolean someCondition = Math.random() < 0.5;
final Supplier<String> s1 = () -> "momField1";
final Supplier<Integer> s2 = () -> Integer.valueOf(667);
final Supplier<String> s3 = () -> "momField10";
final Supplier<String> s4 = () -> "extraField";
FooMom fooMom = new FooMom(s1, s2, s3);
if (!someCondition) {
fooMom = new Foo(s1, s2, s3, s4);
}
}
}
Remark: This is not quite as elegant as the CTOR Chaining solution. However, if the creation/access to resources is the bottleneck, this is the best solution, as data is only created and Lambdas are only run when really needed.
Info: The execution of Lambda expressions in Java is no bit slower than running 'normal' code.
Of course, in the example above, assigning simple String
s is not a situation where one would need this. However, late/Lazy construction of data can be a big advantage in a lot of cases.
Upvotes: 2