Now and Nawoo

NFTの制作記録、技術メモ → C#, Solidity, Blockchain, Bitcoin, Ethereum, NFT

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