1

I have two constructors, which the first one creates some process, like create new objects and without if\for statements. and this constructor cannot be changed, even to private.

But the second constructor get an int value and works like if negative throw exception if positive do some process but if num=0 to avoid duplication of code I want to call first constructor.

What is the right method to implement code like this? Note that these constructors are in the same class.

public class SomeClass{

  public SomeClass() {
    //Do some process
  }

  public SomeClass(int num) {  
    if (num == 0) {
        this(); //here we have an issue
    }
  }
}
Robert Kock
  • 5,795
  • 1
  • 12
  • 20
John D
  • 175
  • 7
  • 2
    Calling a constructor of the current class must be the first statement in another of its constructors. – Arnaud Dec 14 '18 at 14:51
  • You might want to move the code within the first constructor into a new private method. Then call this method from the 2nd constructor in case num=0 – Robert Kock Dec 14 '18 at 14:53
  • @Arnaud I know that, that`s the reason I have post this question. I cannot call from the first line because I need check if num is equal to zero. only in this case I want call a first constructor. – John D Dec 14 '18 at 14:53
  • 1
    `firstConstructor` and `secondConstructor` cannot both be constructors since they cannot both have the same name as the class. – luk2302 Dec 14 '18 at 14:53
  • @luk2302 I guess OP knows that. I edited the question so things are more clear – Robert Kock Dec 14 '18 at 14:56
  • @RobertKock I cannot change any of the code of the first constructor, so I need another solution. The reason of that is because the first constructor made as a given task in a college. – John D Dec 14 '18 at 14:57
  • @luk2302 they have a same name in the code. I will edit my post – John D Dec 14 '18 at 14:58

3 Answers3

3

Create some kind of factory:

public class SomeClass
{
  // This is the original constructor
  public SomeClass()
  {
    // Do some process
  }

  // New constructor expecting num > 0
  private SomeClass(int num)
  {
    // Do whatever you want
  }

  public static SomeClass getIt(int num) throws Exception
  {
    if (num < 0)
      throw new Exception("...");
    else if (num > 0)
      return (new SomeClass(num));
    else
      return (new SomeClass());
  }

} // SomeClass
Guillaume Barré
  • 4,168
  • 2
  • 27
  • 50
Robert Kock
  • 5,795
  • 1
  • 12
  • 20
  • Thanks, Why you declare the second constructor as a private? It should be public – John D Dec 14 '18 at 15:07
  • I like this solution, however we have missing a little thing. if I call getIt method from the second constructor, and we have num > 0, we call again and again the same constructor. and I think you missed return statement in getIt method but this is correctable. – John D Dec 14 '18 at 15:16
  • To answer to "Why you declare the second constructor as a private?"; private member of a class can be accessed by any method of the class static or non-static. – Guillaume Barré Dec 14 '18 at 15:39
  • The `getIt` method is supposed to be called from outside the class, not by the 2nd constructor. I don't see the missing return statement though. – Robert Kock Dec 14 '18 at 16:34
  • The constructor is private in order to force the user of the class to call the factory method. – Robert Kock Dec 14 '18 at 16:35
2

A call to another constructor (this();) must be first in the constructor.

You may want to refactor the code, putting the "processing" logic in a method:

public Constructor() {
    this.processConstructor();
}

public Constructor(int num) {
    if(num == 0) {
        this.processConstructor();
    }
}

private void processConstructor() {
    //Do some process
}
ernest_k
  • 44,416
  • 5
  • 53
  • 99
  • You beat me to it ! :) If I were you, I would change the name of `processConstructor()` to something like `executeProcess()`, just for the sake of comprehension of the solution. – Soutzikevich Dec 14 '18 at 15:02
  • As I said in the post, I cannot change any of the processing logic in the first constructor. I can only edit the second and create new methods. so in this case, this is not useful. please note that the first constructor called only when num equal to zero, in others cases i have another logic process. – John D Dec 14 '18 at 15:03
0

Do it the other way round:

public class SomeClass{

  public SomeClass() {
    this(1 /* or some sensible default */);
  }

  public SomeClass(int num) {
    // Do stuff.
  }
}

As a general principle, you should only to have one constructor which actually "does useful stuff". The other overloads then only exist to provide reasonable default values to invoke that constructor.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243