Polymorphism and Function Overloading in Solidity


Solidity is an object-oriented programming language that supports contract composition. It means combining many contracts or data types together to make complex data structures and contracts.

Solidity also supports inheritance flanked by smart contracts. Inheritance is the process of essential many contracts that are linked to each other over parent-child relationships.

In this post, we will discuss in detail that what polymorphism is in Solidity.


Polymorphism is an aptitude to process data in more than one form. Solidity similarly supports polymorphism like other programming languages.

Types of polymorphism

Polymorphism has the following two types:

  • Function polymorphism
  • Contract polymorphism

Types of polymorphism

Function polymorphism

  • It shapes to stating various functions inside the same contract or inheriting contracts having the same name.
  • The functions vary in the parameter data types.
  • They as well change the number of parameters.
  • Return types are not in a meeting believed for defining valid function signatures for polymorphism.
  • Function polymorphism is also well-known as method overloading.
pragma solidity ^0.4.19;contract helloFunctionPloymorphism {
 function getVariableData(int8 data) public pure returns(int8 output) {
 return data;
 }function getVariableData(int16 data) public pure returns(int16 output) {
 return data;

Contract polymorphism

  • Contract polymorphism means to use multiple contract instances interchangeably when the contracts are related to each other by way of inheritance.
  • Contract polymorphism supports calling the child contract function by using the instance of parent contracts.
pragma solidity ^0.4.19;contract ParentContract {
 uint internal simpleInteger;function SetInteger(uint _value) public {
 simpleInteger = _value;
 }function GetInteger() public view returns (uint) {
 return 10;
}contract ChildContract is ParentContract {

 function GetInteger() public view returns (uint) {
 return simpleInteger;

Function Overloading

  • We can have various definitions for similar function names in the same scope.
  • The definition of the function must vary from each other by the types and the number of arguments in the argument list.
  • We cannot overload function declarations that vary simply by return type.

The below illustration shows the concept of a function overloading in Solidity.

pragma solidity ^0.5.0;
contract Test {
   function getSum(uint a, uint b) public pure returns(uint){     
      return a + b;
   function getSum(uint a, uint b, uint c) public pure returns(uint){     
      return a + b + c;
   function callSumWithTwoArguments() public pure returns(uint){
      return getSum(1,2);
   function callSumWithThreeArguments() public pure returns(uint){
      return getSum(1,2,3);
  • Run the described above program with steps provided in Solidity.
  • Click callSumWithTwoArguments button first.
  • Then CallSumWithThreeArguments button to see the result.


0: uint256: 3

0: uint256: 6

Function Overriding

  • A function that permits an inheriting contract to override its performance will be marked as virtual.
  • The function that overrides the base function should be distinct as an override.
  • Let’s see an example from our preferred library, OpenZeppelin.
  • We will see that the transfer function contains both the virtual and override keywords if we look at the ERC20.sol contract in the latest version of the @openzeppelin/contracts library.
  • Function Overriding
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {      _transfer(_msgSender(), recipient, amount);
      return true;}
  • This means if we inherit the ERC20.sol contract into our project.
  • We may write our individual transfer function and mark it as override since it’s overriding the base transfer function.
  • If we are unable to remember to add the override the compiler will roar at us:
TypeError: Overriding function is missing "override" specifier
  • The motive of the OpenZeppelin transfer function comprises the override keyword is as it’s inheriting the IERC20 interface which also has a transfer function.
  • The whole thing functions in interface contracts are automatically reflected virtual.
  • We must explicitly state which contracts: override(Base1, Base2), if our contract is inheriting the alike function from multiple base contracts.
  • That is unrelated.
pragma solidity >=0.5.0 <0.7.0;
contract Base1
    function foo() virtual public {}
contract Base2
    function foo() virtual public {}
contract Inherited is Base1, Base2
    // Derives from multiple bases defining foo(), so we must explicitly
    // override it
    function foo() public override(Base1, Base2) {}
  • This brings up-to-date makes it strong what functions are meant to be overridden vs what functions should be left as is.
  • This is advantageous when working with libraries such as OpenZeppelin.
  • This is similarly useful if we are building a contract that is meant to be used by other developers.
  • We can be explicit in our intention for a function. If we do not want a function to be overridden, leave off the virtual marker.

Mansoor Ahmed is Chemical Engineer, web developer, a writer currently living in Pakistan. My interests range from technology to web development. I am also interested in programming, writing, and reading.
Posts created 422

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top