What is Inheritance in Solidity?

What is Inheritance in Solidity?

What Is Inheritance in Solidity?

Solidity

Solidity is a programming language. It is designed for developing smart contracts. It is being used for implementing smart contracts on various blockchain platforms particularly Ethereum. To make it familiar for existing web developers this is designed around the ECMAScript syntax. It was developed by Christian Reitwiessner, Alex Beregszaszi, and many former Ethereum core contributors.Solidity also supports inheritance from multiple contracts.

Inheritance in Solidity

Solidity inheritance lets us combine multiple contracts into a single one. The base contracts are the ones from which other inherit. Those contracts that inherit data are derived. This is a process resulting in parent-child relationships between contracts.There are two types of inheritance: single and multi-level. Inheritance marks several linked contracts with a parent-child relationship.It rules highly resemble Python, but they have a few differences. Inheritance creates one contract and places it into the blockchain.The inheritance uses the keyword “is”. 

Example

contract MyContract {
function one() {
//the code
}
}
contract MyOtherContract is MyContract {
function two() {
//code
}
}

We could instantiate MyOtherContract and use function “one” on it:
MyOtherContract myOtherContract = new MyOtherContract();
myOtherContract.one();

This applies to both, properties and functions. However, the keyword “private” on functions, makes functions unavailable in the inheritance graph. Multiple inheritance is also possible as stated above: “SomeContract is ContractA, ContractB, ContractC { }”.

By copying code including polymorphism, Solidity provide support to multiple inheritance . All function calls are virtual that means the most derived functionis called, except when the contract name is explicitly given. Only a single contract is created on the blockchain, and the code from all the base contracts is copied into the created contract when a contract inherits from multiple contracts. The general inheritance system is same as to Python’s especially concerning multiple inheritance. Details are given in the following example.

pragma solidity ^0.4.22;

contract owned {
constructor() { owner = msg.sender; }
address owner;
}

// `is` use to derive from another contract. Derived
// all non-private members including contracts can access
// internal functions and state variables. These cannot be
// externally accessed via `this`, though. contract mortal is owned { function kill() {
if (msg.sender == owner) selfdestruct(owner);
}
}

// These abstract contracts are only given to make the interface known to the compiler.
Note the function
// without body. If a contract does not implement all functions it may only be used as an
interface.
// contract Config {
function lookup(uint id) public returns (address adr);
}
contract NameReg {
function register(bytes32 name) public;
function unregister() public;
}
// Multiple inheritance is possible.Yet there is only a single instance of `owned`Note that 
//`owned` is also a base class of `mortal (as for virtual inheritance in C++).contract named 
//is owned, mortal { constructor(bytes32 name) {
Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
NameReg(config.lookup(1)).register(name);
}
// Functions may be overridden by another function with the same name and the same 
// number/types of inputs.If the overriding function has different types of output parameters, that causes an error.
// local and message-based both function calls take these overrides into account. function kill() public {
if (msg.sender == owner) {
Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
NameReg(config.lookup(1)).unregister();
// It is still possible to call a specific overridden function.
mortal.kill();}}}
// If a constructor takes an argument, it needs to be provided in the header {
function updateInfo(uint newInfo) public if (msg.sender == owner) info = newInfo;}
function get() public view returns(uint r) { return info; } uint info; }

We call mortal.kill() to “forward” the destruction request, note that above. As seen in the following example the way this is done is problematic:

pragma solidity ^0.4.22;

contract owned {
constructor() public { owner = msg.sender; }
address owner;}

contract mortal is owned { function kill() public {if (msg.sender == owner) selfdestruct(owner);}}

contract Base1 is mortal { function kill() public { /* do cleanup 1 */ mortal.kill(); }}

contract Base2 is mortal { function kill() public { /* do cleanup 2 */ mortal.kill(); }}

contract Final is Base1, Base2 { }

As the most derived override, a call to Final.kill() will call Base2.kill , but this function will bypass Base1.kill, basically because it does not even know about Base1. The way around this is to use super:

pragma solidity ^0.4.22;

contract owned {
constructor() public { owner = msg.sender; }
address owner; }

contract mortal is owned { function kill() public {if (msg.sender == owner) selfdestruct(owner);}}

contract Base1 is mortal { function kill() public { /* do cleanup 1 */ super.kill(); }}


contract Base2 is mortal { function kill() public { /* do cleanup 2 */ super.kill(); }}

contract Final is Base1, Base2 { }

It does not simply call this function on one of its base contracts if Base2 calls a function of super. It calls this function on the next base contract in the final inheritance graph, so it will call Base1.kill() with the most derived contract (note that the final inheritance sequence is – starting : Final, Base2, Base1, mortal, owned). The actual function that is called, when using super is not known in the context of the class, where it is used. This is similar for ordinary virtual method lookup.

 

1 thought on “What is Inheritance in Solidity?”

Leave a Comment