15

I was looking at other questions on SO, but I didn't really see an explanation for my question. I read that calling a constructor from another constructor (using the this keyword) was valid, but I didn't understand why it was valid.

Previously, I thought that only one constructor could act per object. Constructor chaining seems to break this logic, in that while calling one constructor, it runs another in conjunction to the original, targeted constructor. Why does constructor chaining work?

Cyclopropane
  • 325
  • 2
  • 10

6 Answers6

14

We chain (call) one constructor from other within the same class so that we can avoid code duplication. Without chaining every constructor, we end up repeating business details and that leads to code duplication and hard to maintain the code as well.

Imagine you are creating a Bus.

public class Bus {  
      int noOfSeats;  
      String busColor;  

      public Bus() {  
           this(40); //// Using another constructor and proceeding with default values..   
      }  
      public Bus(int seats) {   
           this(seats,"red"); // Using another constructor and proceeding..   
      }  
      public Bus(int seats, String color) {  
           this.noOfSeats = seats; 
           this.busColor = color;  
      }  
 } 

And the person using this class can use only constructor at a time, where as you are using chaining internally. Imagine that you have a method which initializes things with default values and calling it in the constructor. There's nothing wrong in that, right?

Just to clarify, the person who is creating the object is calling only one constructor. The invoked constructor calls others which is internal to that class.

JG in SD
  • 5,427
  • 3
  • 34
  • 46
Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
  • 3
    So just to clarify, the programmer's use of internal constructor chaining is allowed, but the user of the class can only call one explicit constructor per object, right? – Cyclopropane Jun 23 '17 at 12:40
  • [That's not the default constructor.](https://stackoverflow.com/q/4488716/476716) – OrangeDog Jun 23 '17 at 15:16
  • 3
    Also, this is a very odd example. You're allowed to have a bus with no seats and no color? Usually you chain them the other way around. – OrangeDog Jun 23 '17 at 15:17
  • @OrangeDog Corrected. default, I mean the no-org constructor. And also, refactored my example completely. Hope this clears up. – Suresh Atta Jun 23 '17 at 15:39
  • @SureshAtta You said that _"Imagine that you have a method which initializes things with default values and calling it in the constructor. There's nothing wrong in that, right?"_. But aren't constructors different from methods in that you can use only constructor per object? So, my question remains: why are you allowed to chain if chaining is like calling multiple constructors per object? – Cyclopropane Jun 23 '17 at 19:23
  • 1
    @KaienYang You're allowed to chain constructors as a language feature to reduce duplication for the benefit of the class (writer) - a class _user_ is still limited to calling a single constructor. – Gwyn Evans Jun 23 '17 at 20:10
  • I understand now! Thanks so much! – Cyclopropane Jun 23 '17 at 20:11
9

Delegated constructors reduce the amount of duplicate code, since you can exploit the functionality set up in one constructor by calling it from another one.

Until this feature was designed into languages, we had to rely on "initialisation"-type functions that were called from constructors. That was a pain for two reasons (i) you could never guarantee that the functions were only called from constructors, and (ii) calling class methods from constructors is always a design "smell".

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    Another downside that is a corollary of (i): fields initialized in initialization methods cannot be declared as final. – dj18 Jun 23 '17 at 16:11
3

It allows to clarify the logic and reduce the code.

Is nesting constructors (or factory methods) good, or should each do all init work

It's reasonable to chain constructors together, the version with fewer parameters calls the version with more parameters. It makes very clear what's happening, and all the real "logic" (beyond the default values) is in a single place. For example:

public class Foo {

    private static final int DEFAULT_X =10;
    private static final int DEFAULT_Y =20;

    private int x;
    private int y;
    private int precomputedValue;

    public Foo(int x, int y) {
        this.x = x;
        this.y = y;
        precomputedValue = x * y;
    }

    public Foo(int x) {
        this(x, DEFAULT_Y);
    }

    public Foo() {
        this(DEFAULT_X, DEFAULT_Y)
    }
}
Yan Khonski
  • 12,225
  • 15
  • 76
  • 114
1

Not a Java dev here, but in Python this is also allowed and pretty much normal.

Whenever you inherit a class, you might want to call the parent class's constructor prior adding your own stuff-and-recipes.

This allows you to benefit the parent class's construction features. Whenever you do not know exactly what the parent class does you most of the time always call it first in order to avoid the parent's class features and methods being broken.

Fabien
  • 4,862
  • 2
  • 19
  • 33
  • Btw, the fact that the OP is using `this` in Java, means that they are not asking about calling a *parent* class constructor. In Java, you need to use `super` to reach a parent class constructor. – Bathsheba Jun 23 '17 at 11:52
  • Yup, the same in Python ( _ _ super() _ _ ), but I did not know for Java. There is no private method per se in Python, so you can call even the 'private' methods. Constructor methods might prove useful if they take parameters, so I guess it makes sense that those are exposed in Java. (In Python constructors do not return values... Don't know for Java) – Fabien Jun 23 '17 at 11:55
1

The fact that the confusion originates from every instance should call one ctor is absolutely right. The constructor chained another is used to avoid code duplication and simplicity because copying same code is really overhead. Sometimes maybe we need two constructors, first one just takes two parameters the other one takes three parameters. But, three parameters-ctor uses same variables of two parameters-ctor. Do you prefer copy-paste same assignmets or merely call the other ctor by this?

0

As a supplement to the other answers, I would like to share another use for calling a constructor from a constructor that I use often.

Another strategy of constructor chaining that I find useful is providing default implementations / auto-injection for Interfaces.

public class Foo {

    private readonly ILogger _logger;

    //Default implementation for most cases
    public Foo() : this(new DefaultLoggerImplementation()) {}

    //DI Constructor that allows for different implementations of ILogger 
   //(Or Mocks in testing)
    public Foo(ILogger logger)
    {
        _logger = logger;
    }

    public void Log(string message)
    {
        _logger.log(message);
    } 
}

This way if you have a default implementation for an interface it is auto injected via new Foo()

If you have a case with different ILogger behavior it is easily injectable, this also promotes the ability to Mock the interface in your unit testing framework.

aspothought
  • 52
  • 2
  • 7