(Part 10) Ethereum Solidity - Multiple inheritance, Diaomond Problem And Function Polymorphism(PT 10)

Repository

https://github.com/igormuba/EthereumSolidityClasses/tree/master/class10

What Will I Learn?

  • Multiple inheritance
  • Diamond problem and how to avoid it
  • Polymorphism in functions

Requirements

  • Internet connection
  • Code editor
  • Browser

Difficulty

  • Intermediate

Tutorial Contents

Solidity allows you to achieve polymorphism, but you need to be careful with some issues this may cause and you need to be mindful of your contract design choices

Multiple inheritance

For this we will use three contracts, the first one is the parent that will have a variable and a function to retrieve it's variable.
The second contract is the "child", it will inherit from the parent but will override the parent's function and will implement its own version of that function calling its own variable.
Then the last contract will inherit from both the parent and the child and will call the function, that has the same name on both the parent and the child

Parent contract

This is the base contract that will be inherited by the next two, it has it's own variable and a function that calls this variable

contract parent{
    uint parentNumber=1; //unique variable to identify we called this contract
    function getNumber() public view returns (uint){ 
        return parentNumber; //returns its unique variable
    }
}

Child contract

This one inherits from the parent and implements its own function and variable so we can identify whether we called the child or the parent, the function from the parent gets overwritten by the new declaration on the child, so the child is parent but has its own implementation of the getNumber() function

contract kid is parent{
    uint kidNumber=2; //variable different from the parent to identify
    function getNumber() public view returns (uint){
        return kidNumber; //returns the kids variable
    }
}

The contract to test

You need to inherit first from the parent, then from the child, both because else you will get an error because of the diamond inheritance problem (more on that later) and because it will help me show you one thing

contract test is parent, kid{ //inherits both
    function callNumber() public view returns (uint){
        return getNumber(); //calls the function that has the same name on both
    }
}

Now, as you can see, the contract test inherits from both the parent and the kid, and it calls the function that has the same name on both, so what do number will show on the result? 1, representing it called the parents variable or 2 for the child?
image.png

It has returned the kids number, even though we have said it to inherit from the parent first!
This is because solidity prioritizes the child that is "the last on the family tree".
We can still call the function from the parent, but first I need to explain why

The diamond problem

image.png

Some programming languages do not allow you to inherit from multiple parents to avoid the diamond problem, Solidity, though, do allow you to inherit from multiple objects.

Inheriting from multiple contracts, in this case, allows you to have some cool features, but you need to be mindful of the functions naming. In case the compiler finds the same method on multiple contracts it will not be able to choose which one are you actually calling.

By saying contract test is parent, kid we are solving the indecision from the compiler by making it explicit that we want the kid function to override the parent one.
If you said, however, contract test is kid, parent it wouldn't make sense because you would tell the compiler that the functions from the parent are overriding the functions from the kid that are overriding the functions from the parent (because kid is parent).

The diamond problem by itself would be worth a whole post, but here are some useful resources on this topic

Higher level explanation of the problem:
http://www.lambdafaq.org/what-about-the-diamond-problem/

In-depth explanation with examples in c++:
https://medium.freecodecamp.org/multiple-inheritance-in-c-and-the-diamond-problem-7c12a9ddbbec

A very good example explaining how Solidity deals with the problem
https://delegatecall.com/questions/multiple-inheritance-question-9dcaa9e4-af20-4518-9a5d-033b11a0d97e

Calling the parent function

In case you want to make a call to the function and get the number from the parent, you need to change the kid and implement this with the keyword super, what super does is it "ignores" that the function was overwritten and goes right into the parent one.

Let me show with an example, on the code below the only thing that changes is the kid contract

pragma solidity ^0.5.0;

contract parent{
    uint parentNumber=1;
    function getNumber() public view returns (uint){
        return parentNumber;
    }
}

contract kid is parent{
    uint kidNumber=2;
    function getNumber() public view returns (uint){
        return super.getNumber(); //searches for this function on the parent
    }
}

contract test is parent, kid{
    function callNumber() public view returns (uint){
        return getNumber();
    }
}

image.png

As you can see, this time the parent number was called because we told the kid to search for the function on the parent contract.

One function with many forms

Polymorphism means many forms, the same way that contracts can have many forms, functions also can have many forms. One beautiful thing on polymorphism is that you can have multiple functions with the same name if the signature from the functions is different. That means if they have different inputs. In practice, this is as if there is only one function, but this one function has many forms, hence, the word polymorphism

See the example below

pragma solidity ^0.5.0;

contract polymorphism {
    function manyforms(uint numberOne) public pure returns (uint){ //fist form of function manyforms
        return numberOne;
    }
    function manyforms(uint numberOne, uint numberTwo) public pure returns(uint){ //second form of function manyforms
        return numberOne+numberTwo;
    }
}

On the example above we have successfully implemented two functions with the exact same name, but we have had no errors raised from the Solidity compiler because their signature is different from each other, in this case, the Solidity code will choose which one to call based on the signature of the caller, if you pass to the function manyforms() only one number, the first one will be executed, if you pass two, there will be no ambiguity because it is obvious to the computer that you mean to call the second one that deals with two arguments

Calling a polymorphed function

With a third function, we can test the polymorphed function manyforms, check the newly added function below

pragma solidity ^0.5.0;

contract polymorphism {
    function manyforms(uint numberOne) public pure returns (uint){
        return numberOne;
    }
    function manyforms(uint numberOne, uint numberTwo) public pure returns(uint){
        return numberOne+numberTwo;
    }
    function callOneForm() public pure returns (uint){
    //some code here
    }
}

Inside the callOneForm we can choose whether we want to send one or two arguments. For this we call the function manyforms() and we can either pass one or two numbers, like in

function callOneForm() public pure returns (uint){
    manyforms(1);
    }

or in

function callOneForm() public pure returns (uint){
    manyforms(1,3);
    }

Doing the first form first, the one that receives only one number and calling the callOneForm()
image.png

And now on the second form with 1 and 3 as arguments (notice that you have to compile and deploy the contract again)

image.png

You can keep on adding more forms, maybe you would like to add another manyforms function that sums multiple numbers, this allows you to design more concise contracts, with the same functionality but prepared to receive different sets of arguments.

Curriculum

Beneficiaries

This post has as beneficiaries
@utopian.pay with 5%
using the SteemPeak beneficiary tool
image.png

H2
H3
H4
Upload from PC
Video gallery
3 columns
2 columns
1 column
8 Comments