Solidity supports object oriented programming paradigm of inheritance. Inheritance means adding extra functionality to a contract by inheriting them from another contract.
We could want some functionality in our contract and instead of defining and implementing them from scratch, we could just inherit it from a base or parent contract.
Inheritance of a contract in solidity is done by the is
keyword. Solidity supports multiple inheritance; meaning you can inherit from more than one parent contract.
Inheritance tips
Inheritance is done by using the
is
keyword to inherit from a base contract.A Function in the parent contract that should be overridden by the child contract should be declared as virtual.
A child contract that will override the parent function must use the keyword override.
Order of inheritance is important.
pragma solidity ^0.8.4;
interface Bonny {
//we defined an interface to force contract inheriting that interface to implement the methods define n the interface
function gethelp() external view returns (string memory);
}
contract BaseContract{
//the key world virtual is used to defined a function that will be overiden by the child contract
function actWise() public view virtual returns (string memory){
return "Base is wise";
}
function hello() public view returns (string memory){
return "Hello Motor";
}
}
contract A is BaseContract {
function sayHello() public view returns (string memory){
//we are calling the hello function in the BaseContract
return hello();
}
//we have overridden the base contract actWise function with our own implementationof it
function actWise() public view virtual override returns (string memory){
return "Contract A is wise";
}
}
contract B is BaseContract {
//we have overriden the base contract actWise function with our own implementationof it
function actWise() public view virtual override returns (string memory){
return "Contract B is wise";
}
}
contract D is A, B, Bonny {
function actWise() public view override(A,B) returns (string memory){
//super refers to the parent of the derived contract
//if the inheritance is multiple super refers to the right most parent. In this case super refers to B
return super.actWise();
}
function gethelp() public view returns (string memory){
return "help me please!";
}
}
The example above consist of a base contract named BaseContract. The BaseContract
defines two methods named actWise
and sayHello
.
The function actWise
is defined as virtual which means contracts inheriting (derived contracts) it, has an option to declare and execute their own implementation of the function actWise
.
This is seen by function A
and B
which inherits from the BaseContract
and implemented their own versions of actWise
by using the override
keyword.
If you look closely at function actWise
in both contract A
and B
,you will notice that it still contain the virtual keyword. We made it so, so that any contract inheriting from them also have the option of overriding the actWise
function.
Looking at contract D
you can see that it inherits from both contract A
and contract B
. There is also a third inheritance from an interface called Bonny
.
Before, I progress. What is an interface?
I answer my own question by defining an interface as a set of functions that a contract inheriting it must define and implement.
An interface only defines the function name and signature without implementation. The inheriting contract will not compile if the function defined on the interface is not implemented.
An interface is defined using the interface
keyword followed by the name of the interface. The functions defined in an interface must be external without a function body.
An interface cannot have a constructor and it does not make use of any state variable.
Coming back to earth
contract D is A, B, Bonny {
function actWise() public view override(A,B) returns (string memory){
//super refers to the parent of the derived contract
//if the inheritance is multiple super refers to the right most parent. In this case super refers to B
return super.actWise();
}
function gethelp() public view returns (string memory){
return "help me please!";
}
}
We actwise
function was overridden in both parent contract A
and B
(remember, we also defined the actWise
function in contract A and B as virtual which means we can override it).
In our implementation, we decided to call the parent contract actWise
function using the keyword super
which means the parent contract. Since contract D has two parents that both have the actWise
function; the parent at the most right hand side of the inheritance which is contract B
will be called by super.
This example shows that the order of inheritance is important when you have more than one parent contract you are inheriting from.
Take away from the lesson:
- Solidity supports multiple inheritance
- Order of inheritance matter
- An interface is a set of functions that a derived contract must implement
- Inheritance is used to add extra functionality to our contracts.
Until next time, happy coding....
Top comments (0)