Skip to main content

Command Palette

Search for a command to run...

Inheritance

Published
8 min readView as Markdown
Inheritance

Inheritance

  1. Inheritance is a fundamental concept in object-oriented programming, and Solidity supports inheritance in its contracts.

  2. Inheritance allows a contract to inherit properties and behavior from another contract, which can help reduce code duplication and improve code reusability.

  3. In Solidity, a contract can inherit from another contract using the is keyword, followed by the name of the base contract. Here's an example:

contract Animal {
    string public name;
    uint public age;

    constructor(string memory _name, uint _age) {
        name = _name;
        age = _age;
    }

    function eat() public virtual returns (string memory) {
        return "The animal is eating.";
    }
}

contract Dog is Animal {
    string public breed;

    constructor(string memory _name, uint _age, string memory _breed) Animal(_name, _age) {
        breed = _breed;
    }

    function bark() public returns (string memory) {
        return "Woof!";
    }

    function eat() public override returns (string memory) {
        return "The dog is eating.";
    }
}
  1. In this example, we have two contracts: Animal and Dog. The Dog contract inherits from the Animal contract using the is keyword. This means that the Dog contract inherits all the properties and functions of the Animal contract, including the name and age properties and the eat() function.

  2. The Dog contract also adds its own property, breed, and its own function, bark(). The Dog contract overrides the eat() function from the Animal contract using the override keyword, which allows the Dog contract to provide its own implementation of the eat() function.

  3. With inheritance, the Dog contract can use all the properties and functions from the Animal contract, as well as its own properties and functions. This can help reduce code duplication and improve code reusability by allowing you to define common properties and functions in a base contract and then inherit from that contract in other contracts.

  4. Note that in Solidity, you can also use multiple inheritance, where a contract inherits from multiple base contracts. To do this, you simply list the base contracts separated by commas in the contract declaration. However, be careful when using multiple inheritance, as it can make your code more

Parent Constructor

  1. In Solidity, you can call a parent contract's constructor using the super keyword.

  2. Here's an example of how to call the parent constructor in a derived contract:

pragma solidity ^0.8.0;

contract Parent {
    uint public x;

    constructor(uint _x) {
        x = _x;
    }
}

contract Child is Parent {
    uint public y;

    constructor(uint _x, uint _y) Parent(_x) {
        y = _y;
    }
}
  1. In the example above, Child is a derived contract that inherits from Parent. Child has its own constructor that takes two arguments: _x and _y.

  2. To call the parent constructor with _x, we use Parent(_x) in the Child constructor. This tells Solidity to execute the Parent constructor with the _x argument passed to the Child constructor.

  3. Note that if the parent contract has a constructor with arguments, the derived contract must provide values for those arguments when calling the parent constructor using super.

Super Keyword in Solidity

  1. In Solidity, super is a keyword used to call functions or constructors defined in a parent contract from a child contract that inherits from it.

  2. super is used to access functions and state variables defined in the parent contract.

  3. It can be used to call functions with the same name in the parent contract or to call the parent constructor from the derived contract constructor.

Here are a few examples of how super can be used in Solidity:

  1. Calling a function in the parent contract:
csharpCopy codepragma solidity ^0.8.0;

contract Parent {
    uint public x;

    function foo() public virtual {
        x = 1;
    }
}

contract Child is Parent {
    function foo() public override {
        super.foo();
        // do something else
    }
}

In this example, Child overrides the foo function from Parent. The foo function in Child calls super.foo(), which calls the foo function in Parent and sets x to 1.

  1. Calling the parent constructor from the derived contract constructor:
pragma solidity ^0.8.0;

contract Parent {
    uint public x;

    constructor(uint _x) {
        x = _x;
    }
}

contract Child is Parent {
    uint public y;

    constructor(uint _x, uint _y) Parent(_x) {
        y = _y;
    }
}
  1. In this example, Child calls the parent constructor using Parent(_x) in its own constructor.

  2. This passes the _x argument to the Parent constructor and initializes the x variable in the Parent contract. The Child constructor then initializes its own y variable with the _y argument.

  3. Overall, super is an important keyword in Solidity that allows for inheritance and code reuse in smart contract development.

Method Overriding in Solidity

  1. Method overriding is a feature of object-oriented programming that allows a subclass to provide its own implementation of a method that is already defined in its superclass. In Solidity, method overriding can be used when one contract inherits from another contract.

  2. To override a method in a derived contract, the derived contract must define a function with the same name and function signature as the function in the parent contract.

  3. The override keyword is used to indicate that the derived contract is overriding the parent contract's function.

Here's an example:

pragma solidity ^0.8.0;

contract Parent {
    function foo() public virtual {
        // parent implementation of foo
    }
}

contract Child is Parent {
    function foo() public override {
        // child implementation of foo
    }
}
  1. In this example, Child overrides the foo function from Parent. The override keyword is used to indicate that Child is intentionally overriding the foo function from Parent.

  2. When a contract calls the foo function on an instance of Child, the implementation in Child will be executed instead of the implementation in Parent.

  3. It's important to note that if a contract overrides a function, the function must be marked as virtual in the parent contract.

  4. Otherwise, Solidity will generate a warning. Additionally, if the function is marked as external or public, it must have the same visibility in the derived contract.

Method Resolution In Solidity

  1. Method Resolution Order (MRO) is the order in which methods are searched for in a class hierarchy. In Solidity, MRO is used to determine which implementation of an overridden function is called when a function is called on an instance of a derived contract.

  2. Solidity uses a linearized MRO, also known as C3 linearization, to determine the order in which methods are searched for in the inheritance hierarchy.

  3. The linearization algorithm ensures that the order preserves the desired properties of inheritance, such as monotonicity and local precedence ordering.

Here's an example:

pragma solidity ^0.8.0;

contract A {
    function foo() public virtual returns (string memory) {
        return "A";
    }
}

contract B is A {
    function foo() public virtual override returns (string memory) {
        return "B";
    }
}

contract C is A {
    function foo() public virtual override returns (string memory) {
        return "C";
    }
}

contract D is B, C {
    function foo() public override(B, C) returns (string memory) {
        return super.foo();
    }
}
  1. In this example, D is a derived contract that inherits from B and C, which both inherit from A. D overrides the foo function from A, and super.foo() is used to call the implementation of foo in the linearized MRO of the parent contracts (B and C).

The linearization of D is calculated as follows:

L(D) = [D] + merge(L(B), L(C), [B, C])

where merge combines the linearizations of B and C with the B and C themselves, in the order they are provided.

  1. The resulting linearization of D is [D, B, C, A], which means that when the foo function is called on an instance of D, it will first look for the implementation in D, then in B, then in C, and finally in A. If the function is not found in any of those contracts, a runtime error will occur.

  2. By using a linearized MRO, Solidity ensures that the correct implementation of an overridden function is called, even in complex inheritance hierarchies.

Method Overloading

  1. Method overloading is a feature of object-oriented programming that allows a class to have multiple methods with the same name but different parameter lists. In Solidity, method overloading can be used to provide multiple functions with the same name that perform different operations based on the input parameters.

  2. Solidity supports method overloading by allowing functions to have the same name, but with different parameter lists. The functions must differ in the number or types of their parameters.

Here's an example:

pragma solidity ^0.8.0;

contract Overloading {
    function foo(uint256 x) public pure returns (uint256) {
        return x * 2;
    }

    function foo(string memory s) public pure returns (string memory) {
        return s;
    }
}
  1. In this example, the Overloading contract defines two functions named foo, one that takes a uint256 parameter and returns a uint256 value, and another that takes a string parameter and returns a string value.

  2. When a contract calls the foo function on an instance of Overloading, Solidity will determine which function to call based on the number and types of the input parameters.

For example:

Overloading o = new Overloading();
uint256 x = 42;
string memory s = "hello";

uint256 result1 = o.foo(x);  // calls foo(uint256)
string memory result2 = o.foo(s);  // calls foo(string)
  1. In this example, the first call to foo with a uint256 parameter will call the first foo function in Overloading, while the second call to foo with a string parameter will call the second foo function.

  2. t's important to note that while Solidity allows method overloading, it does not support method overriding with the same function signature. If two functions in a contract have the same name and function signature, a compile-time error will occur.