18

If I have 2 constructors in my custom class and one of them takes an extra argument and does everything the first one does but with just one additional line of code (and this extra line utilises the extra argument), how best to deal with this without having to duplicate all the code in the first constructor?

Example code

public myConstuctor(int number, int number2){

    int result = (number + number2);
    int result2 = (number2 - number1)

    //Etc
    //Etc
    //Etc
    //Etc

}

public myConstructor(int number1, int number2, int number 3){

    int result = (number + number2);
    int result2 = (number2 - number1)

    //Etc
    //Etc
    //Etc
    //Etc

    int result3 = (result + result2 + number3)


}
Zippy
  • 3,826
  • 5
  • 43
  • 96
  • No, it's not the same question, I'm not specifically asking how to call one constructor from another one, I'm asking how to deal with the problem of cutting down on duplicate code, regardless of the most popular answer possibly being to do just that (call one constructor from the other) – Zippy Aug 12 '13 at 16:33
  • "I'm asking how to deal with the problem of cutting down on duplicate code," you chose as correct not the correct answer.. is better to put the logic in the constructor with more parameters – nachokk Aug 12 '13 at 18:34
  • @nachokk, If I create an object that requires only 1 argument, then it doesn't need code in the 2-argument constructor, so the bulk of my logic (all common logic) is in the constructor with the *least* arguments, when I need to create an object passing 2 arguments, then all the logic in the original 1-argument constructor will still need to be run as it's common to all objects of this type, but will also need the additional code in the 2-argument constructor, I refer back to the 1-argument constructor and run the common code, then, run the extra code in the other. Seems perfectly logical? – Zippy Aug 12 '13 at 20:20
  • What i want to say if you do in the way @bas suggest , you only put the logic in one constructor, in the other hand you have to put logic in both constructor! – nachokk Aug 12 '13 at 20:23
  • @nachokk, no I only have the bulk of my code in one constructor (single argument constructor) - the only code I have in the other constructor (2 argument constructor) is the code that is required for objects that need it so, no code is duplicated now! :-) – Zippy Aug 12 '13 at 22:46

4 Answers4

24

You can make the second constructor call the first one:

public MyClass(int number1, int number2, int number3) {
    this(number1, number2);
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • mmm don't know why 5 upvotes, @bas answer is correct – nachokk Aug 12 '13 at 16:25
  • Perfect. implemented and working great :-) – Zippy Aug 12 '13 at 16:38
  • 1
    @nachokk: Both answers are correct. I generally prefer to have constructors with fewer arguments call those with larger arguments. The op's case is presented in a way that suggests that such an ordering might not be possible, so SLaks took the safe route and presented an answer which more closely matched the OP's code. If there is no possible default value for number3, bas's answer is not an option (unless you add a sentinel value or make number3 nullable). Some people would argue that SLaks' approach is cleaner, since it makes many small constructors rather than one giant one). – Brian Aug 13 '13 at 20:05
  • a constructor taking 3 arguments is almost always a mistake. At this point it would probably be better to have a Map in case at some point you have to add a number4 to the constructor, and not have to change the prototype of the constructor. – Dmytro Aug 19 '16 at 20:45
18

You can call the other constructor and put all of your logic there.

public myConstructor(int number, int number2){
    this(number, number2, 0);
}

public myConstructor(int number1, int number2, int number3){

    int result = (number + number2);
    int result2 = (number2 - number1)

    //Etc
    //Etc
    //Etc
    //Etc

    int result3 = (result + result2 + number3)


}
bas
  • 1,678
  • 12
  • 23
  • What if number3 multiplies some value? Say `result2 *= number3`? – Math Aug 12 '13 at 16:24
  • Depending on the structure of the constructors, SLaks answer might be better. This approach means that the user could have called `myConstructor` with 3 arguments, but instead a default argument is used for number3. @Math in your case the default call could be `this(number, number2, 1);` – bas Aug 12 '13 at 16:25
  • 2
    I just said that because I think your solution will depend on what the constructor does, and Slaks' answer seem to me that covers all possibilities.. Not that yours is wrong, but will depend on what the constructor does. – Math Aug 12 '13 at 16:29
  • 2
    @Math You are correct, but generally it is better to call the constructor with more arguments from the constructor with less arguments, since usually a default value is required or implied for the missing arguments. – Trevor Freeman Aug 12 '13 at 17:32
  • It's pretty meaningless to have result, result2, result3 as local variables instead of data members, declared in the enclosing class. – smci Aug 27 '13 at 21:57
7

You can also use a builder pattern if the arguments get too many to manage:

MyClass obj = Myclass.set1(number1).setN2(number2).setN3(number3).build();

build() can call the cumbersome constructors.

rocketboy
  • 9,573
  • 2
  • 34
  • 36
0

Just use the first constructor method inside the second constructor method, and afterwards...just add the new line needed in the Second Constructor method.

public ClassName(arg1, arg2){
   //etc
}


public ClassName(arg1,arg2,arg3){
 this(arg1,arg2);
 //new line of code to deal with arg3;
}

And thats it :) lots of time saved.

S.H.
  • 2,833
  • 3
  • 26
  • 28