继承基础知识
- 继承定义方法、is关键字
- 变量与函数、modifier、event的可见性
继承的方式
继承的实现本质就是代码拷贝,所以继承合约之后,部署到网络就成为了一个合约。父合约的代码被拷贝进子合约中。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Name {
//对于成员变量,在private可见性下。父子合约并不会出现命名冲突
uint private num = 1;
uint public num = 1;
uint external num = 1;
//但是对于函数,private并不能解决命名冲突的问题;具体原因不得而知
function foo() private {}
//event modifier 都会造成命名冲突
}
contract Name2 is Name {
uint private num = 1;
function foo()private {}
}
- 构造函数的语法 构造函数的语法有两种方式
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract Base {
constructor(string memory name){
}
}
// 1
contract Name2 is Base("name") {
}
// 2
contract Name3 is Base {
constructor()Base("name") {
}
}
构造函数也可以接受location为storage的参数
此时Base就必须被标识为abstract合约(即:必须被继承的合约);
原因可想而知,既然是storage的参数,那证明参数接受的是一个成员变量。
那什么情况下才能接受到一个成员变量作为参数那?答案就是被继承的时候,子合约将自身的成员变量传入Base合约。那Base合约就成为了抽象合约,因为构造函数的参数为storage,所以只有被继承的情况下,Base合约才有意义
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
abstract contract Base {
constructor(string storage name){
}
}
contract Name2 is Base {
string name = "name";
constructor()Base(name) {
}
}
有关多态的基础知识
- override virtual关键字 之前说:对于函数,private并不能解决命名冲突的问题;
而override virtual关键字,解决了这个问题,父合约virtual 子合约override进行函数覆盖
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
//在这里我们可以不断的尝试父子合约不同的可见性的关键词或者不同的修饰(view pure),来查看会出现什么问题
contract Name {
// function foo() external virtual {}
// function foo() private virtual {}
// function foo() internal view virtual ;
// function foo() internal pure virtual ;
function foo() internal virtual {}
}
contract Name2 is Name {
// function foo() external override {}
// function foo() public override {}
// function foo() public pure override {}
// function foo() public view override {}
function foo() internal override {}
}
我们也可以选择在Base合约不去设置实现体;此时Base合约应被标记为抽象合约
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
abstract contract Name {
function foo() internal virtual ;
}
contract Name2 is Name {
function foo() internal override {}
}
多重继承c3线性
算法理解
比较抽象-->比较具体 算法描述
示例: g-->f-->e-->a(有未遍历的子节点)--->回溯到e找c(有未遍历的子节点)--->回溯找d--->c-->依次推