Solidityの学習メモ: 継承
継承についてのメモ。
親のコンストラクタの引数を指定する方法
contract A { constructor (uint a) {} // Aのコンストラクタは引数が必要 } // コンストラクタで指定 contract B is A { constructor() A(1) {} } // または is で指定 contract B is A(1) { }
多重継承と順番
多重継承する場合、基本コントラクトから派生コントラクトの順番で指定する必要がある。
contract A {} contract B is A {} contract C is B, A {} // TypeError: Linearization of inheritance graph impossible contract D is A, B {} // これならOK
Contracts — Solidity 0.8.7 documentation
継承とコンストラクタ
公式ドキュメントに
派生コントラクトがその基本コントラクトのすべてのコンストラクターへの引数を指定しない場合、それは抽象になります。 Contracts — Solidity 0.8.7 documentation
とあって、よくわからなかったので実際にコードを書いて試してみた。
contract A { constructor (uint a) {} // Aのコンストラクタは引数が必要 } contract B is A(1) {} // Aの引数を指定すればOK contract C is A {} // Aの引数を指定しないと TypeError: Contract "C" should be marked as abstract. abstract constract C is A {} // abstractをつければOK
では、abstractのCを継承した場合、どうやって引数を指定するのか?
// コンストラクタでAの引数を指定 contract D is C { constructor () A(1) {} } // 多重継承にしてもいい contract E is A(1), C {}
例えば、OpenZeppelinのERC721EnumerableはERC721を継承しているが、ERC721のコンストラクタの引数を指定していないので abstractになっている。 つまり、ERC721Enumerableを継承してMyNFTを作った場合は、constructorで ERC721の引数を指定する必要がある。 (なんか違和感がある書き方だと思っていたが、納得できた。)
abstract contract ERC721Enumerable is ERC721, IERC721Enumerable {...} contract MyNFT is ERC721Enumerable { constructor() ERC721("Name", "Symbol") {} }
openzeppelin-contracts/ERC721Enumerable.sol at master · OpenZeppelin/openzeppelin-contracts · GitHub