Cyclopropane
Cyclopropane

Reputation: 325

Why are you allowed to call one constructor from another?

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?

Upvotes: 15

Views: 6830

Answers (6)

Suresh Atta
Suresh Atta

Reputation: 121998

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.

Upvotes: 14

aspothought
aspothought

Reputation: 52

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.

Upvotes: 0

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?

Upvotes: 1

Yan Khonski
Yan Khonski

Reputation: 13083

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)
    }
}

Upvotes: 3

Fabien
Fabien

Reputation: 4972

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.

Upvotes: 1

Bathsheba
Bathsheba

Reputation: 234665

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".

Upvotes: 9

Related Questions