Constructors

Defining Initial Values

As with other object-oriented languages, constructors allow us to define the values of state variables at contract deployment time. The syntax for defining a contract constructor is as follows:

constructor() {}

To motivate our understanding of constructors in Solidity, let's try creating a student contract whose values will be defined at deployment-time

contract Student {

    uint256 age;
    string name;
    
    constructor(uint studentAge, string memory studentName) {
        age = studentAge;
        name = studentName;
    }

}

In the example above, our constructor takes in two arguments: studentAge and studentName. These two arguments are then used to define the state variables age and name. Note that when defining state variables in constructors, said state variables must already be declared in the contract body (i.e. not within a function body). As an example, the following code would not compile because age, although declared within the contract constructor, was declared as a local variable.

contract Student {

    constructor(uint studentAge, string memory studentName) {
        uint256 age = studentAge;
        string memory name = studentName;
    }

    function getAge() public view returns(uint256) {
        return age;
    }

}

Calling Parent Constructors

In the Interfaces and Inheritance section, we saw that child contracts can call the functions of parent contracts via the super keyword. Child contracts are able to call the constructor of parent contracts via two different methods.

Focusing first on the constructor function itself, the syntax for calling a parent constructor is as follows:

constructor() parentConstructor() {}

As an example, if we are defining the constructor of contract B, and we wish to call the constructor of parent A, we can write the following:

contract A {

    constructor(uint num) {}

}

contract B is A {

    constructor(uint num) A(num) {}

}

Notice that when calling parent constructors, we can pass in the argument values of the child constructors; in the example above, we pass in the parameter num as the argument for the constructor of A.

The other way to call a parent constructor focuses on the contract header; the syntax for this is as follows:

contract A {

    constructor(uint num) {}

}

contract B is A() {

    constructor(uint num) {}

}

As seen above, in line 7, we are calling the constructor of parent contract A. One thing to note though is that for parent constructors called in the child contract header, we cannot pass in arguments from the child constructor (i.e. the values passed to the parent constructor must be explicitly declared). As an example, the following code would not compile:

contract A {

    constructor(uint num) {}

}

contract B is A(num) {

    constructor(uint num) {}

}

Order of Constructors

If a child contract inherits multiple contracts, then the order in which the constructors of the parent contracts are called (regardless of how a user orders them in the constructor header) is defined by the order in which the contracts are inherited by the child contract. As an example, if we have: contract C is A, B

then the constructor of A is always executed before the constructor of B. Therefore, the following code is equivalent: constructor() A() B() {}

constructor() B() A() {}

Resources

Last updated