Inheritance of Contracts
Inheritance is a very important feature of object-oriented programming. Its benefits are:
- extending functionality of a contract (program),
- separate code,
- reduce dependencies
- increase re-usability of existing code
When a contract inherits from another contract, only a single contract is created on the blockchain. The code from all the base contracts is compiled into the created child contract.
Single Inheritance
In this example, we show how a contract can inherit from another contract.
pragma solidity 0.8.20;
// Defining the parent contract
contract parent{
uint internal sum;
uint256 a;
uint256 b;
function setValue(uint256 _a, uint256 _b) external {
a = _a;
b = _b;
}
}
/ Defining the child contract
contract child is parent{
function sumUp() external returns(uint) {
return a + b;
}
}
In lines 4 – 14 we define the parent contract. It has a function setValues(). And in line 17, we define the child contract. The inheritance is done with the keyword is.
When deploying the child contract, the function setValues() defined in the parent contract is also available in the child contract.
In the previous example, we inherited a single function. But it is also possible to inherit modifiers, variables, and constructors.
Inheriting a Constructor
If the parent constructor has no parameter, the child contract inherits it like a normal function. But if the parent constructor expects any parameters, the child constructor needs to be called like that.
The parent constructor in the parent contract:
constructor(uint256 number){
owner = msg.sender;
}
The child constructor in the child contract:
constructor() Parent(10){}
you can find the full code here:
pragma solidity 0.8.17;
// Defining the parent contract
contract Parent{
uint internal sum;
uint256 a;
uint256 b;
uint256 public number;
address public owner;
constructor(uint256 _number){
owner = msg.sender;
number = _number;
}
function setValue(uint256 _a, uint256 _b) external {
a = _a;
b = _b;
}
}
// Defining the child contract
contract Child is Parent{
constructor() Parent(10){}
function sumUp() external view returns(uint) {
return a + b;
}
}
Function Overriding
Functions of the child contract can override functions of parent contracts if they are marked as virtual. The overriding function must use the keyword override in its header.
There are several rules to follow when changing the visibility and mutability of the base function: https://docs.soliditylang.org/en/latest/contracts.html#inheritance
The following example shows how to override an inherited function.
pragma solidity 0.8.20;
// Defining the parent contract
contract Parent{
uint256 public number;
function overrideFunction(uint256 _number) virtual external {
number = _number;
}
}
// Defining the child contract
contract Child is Parent{
function overrideFunction(uint256 _number) override public {
number = _number + 1;
}
}
You can see that the child function changes the visibility from external to public. Besides, there is also different code in the function body.
It is important to know that a function does not override another function if the parameters are different. If our base function had no parameter, the child function would not override it. Instead, the compiler would error if you try to override this function.
function overrideFunction() virtual external {
}
But you can declare two functions with the same name but different parameters.
Multiple Inheritance and Linearization
It is possible that multiple contracts inherit from a single contract.
It is also possible that contracts inherit from contracts that inherit from a base contract.
It is also possible to inherit from multiple contracts.