Солидность
Solidity — это язык программирования. Он предназначен для разработки смарт-контрактов. Он используется для реализации смарт-контрактов на различных блокчейн-платформах, в частности на Эфириуме. Чтобы сделать его знакомым для существующих веб-разработчиков, он разработан на основе синтаксиса ECMAScript. Он был разработан Кристианом Рейтвиснером, Алексом Берегсаси и многими бывшими основными участниками Ethereum. Solidity также поддерживает наследование от нескольких контрактов.
Наследование в Solidity
Наследование Solidity позволяет нам объединять несколько контрактов в один. Базовые контракты — это контракты, от которых наследуются другие. Те контракты, которые наследуют данные, являются производными. Это процесс, в результате которого между контрактами устанавливаются отношения родитель-потомок. Существует два типа наследования: одиночное и многоуровневое. Наследование помечает несколько связанных контрактов отношениями родитель-потомок. Правила очень похожи на Python, но имеют несколько отличий. Наследование создает один контракт и помещает его в блокчейн. При наследовании используется ключевое слово «есть».
Пример
contract MyContract {
function one() {
//код
}
}
contract MyOtherContract is MyContract {
function two() {
//код
}
}
Мы могли бы создать экземпляр MyOtherContract и использовать для него функцию one:
MyOtherContract myOtherContract = new MyOtherContract();
myOtherContract.one();
Это относится к обоим , свойства и функции. Однако ключевое слово «частное» в функциях делает функции недоступными в графе наследования. Множественное наследование также возможно, как указано выше: «SomeContract is ContractA, ContractB, ContractC {}».
Копируя код, включая полиморфизм, Solidity обеспечивает поддержку множественного наследования. Все вызовы функций являются виртуальными, что означает, что вызывается наиболее производная функция, за исключением случаев, когда имя контракта указано явно. В блокчейне создается только один контракт, а код всех базовых контрактов копируется в созданный контракт, когда контракт наследуется от нескольких контрактов. Общая система наследования такая же, как и в Python, особенно в отношении множественного наследования. Подробности приведены в следующем примере.
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; }
Мы вызываем mortal.kill()
, чтобы «переслать» запрос на уничтожение, обратите внимание на это выше. Как видно из следующего примера, способ, которым это делается, проблематичен:
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 { }
Как наиболее производное переопределение, вызов Final.kill()
вызовет Base2.kill
, но эта функция обойдет Base1.kill
, в основном потому, что она даже не знает о Base1
. Обойти это можно с помощью 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 { }
Он не просто вызывает эту функцию для одного из своих базовых контрактов, если Base2
вызывает функцию super
. Она вызывает эту функцию для следующего базового контракта в окончательном графе наследования, поэтому она будет вызывать Base1.kill()
с наиболее производным контрактом (обратите внимание, что окончательная последовательность наследования — начало: окончательный, базовый2, базовый1, смертный, принадлежащий). Фактическая функция, которая вызывается при использовании super, неизвестна в контексте класса, в котором она используется. Это похоже на поиск обычного виртуального метода.
Для получения более подробной информации посетите: https://www.technologiesinindustry4.com/2020/12/what-is-inheritance-in-solidity.html