How to override functions in Solidity | Explaining override and virtual

In this tutorial, we are going to learn how to override functions from the parent smart contracts in Solidity and explain what the virtual and override keywords do.

In this tutorial, we are going to learn how to override functions from the parent smart contracts in Solidity and explain what the virtual and override keywords do.

As you may know, your Solidity smart contracts can inherit from other smart contracts which makes your smart contract use the implementation of the parent smart contract and you can build on top of that implementation.

If you want to change the behaviour of a function from the parent smart contract, you'll need to override it.

To override a function in Solidity, you need to define a function:

  • with the exact same name
  • with the exact same parameters
  • with the same return type

So it has the same signature and Solidity understands what function you override. Function signatures are basically the combination of the name, parameters and return type and they are used to identify a function.

The other requirements to override a function are that:

  • the visibility of the functions needs to be the same (if the function you override is internal, you can't override and make it public)
  • the function in the parent smart contract needs to be virtual

Marking a function as virtual allows smart contracts that inherit from your smart contract to override that function.

Then the function in the child smart contract needs to use the override keyword.

Example:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.9;

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

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

In the example above, the smart contract B inherits from A and overrides the foo function which is marked as virtual in A and in B it uses the override keyword.

If you smart contract inherits from multiple smart contracts, you need to pass the smart contracts it inherits from to the override keyword and you need to pass them with the exact same order as it is in your smart contract definition.

Here is an example:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.9;

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

contract B {
    function foo() internal virtual returns (string memory) {
        return "B";
    }
}

contract C is A, B {
    function foo() internal override(A, B) returns (string memory) {
        return "C";
    }
}

Here is another example where B inherits from A as well:

// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.9;

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

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

contract C is A, B {
    function foo() internal override(A, B) returns (string memory) {
        return "C";
    }
}

You can see that in this case, you have to combine both virtual and override in B.

And that's it 🎉

Thank you for reading this article, if you want to get better at blockchain development, leave your email below and you'll get:

  • access to the private Discord of a community of Web3 builders
  • access to free guides that will teach you Blockchain Development