2022/06/23 Solidity_Day6

# 2022/06/23 Solidity_Day_No4

### 修改器重写

**可重写的修改器也需要用`virtual`修饰,同样需要用`override`进行重载:**

**示例代码:**
`
pragma solidity ^0.8.0;

contract ModifierOverride {
// 声明一个修饰器
modifier foo() virtual {_;}
}

// 声明一个派生合约重写上诉的修饰器
contract Inherited is ModifierOverride {
modifier foo() override {_;}
}

// 如果派生合约继承了多个基类合约并且基类合约当中存在同名可重写修饰器那么重写的时候需要显示指定
contract B {
modifier foo() virtual {_;}
}

// 声明一个合约继承B和ModifierOverride
contract C is B, ModifierOverride {
modifier foo() override(B, ModifierOverride) {_;}
}
`

### 构造函数

**构造函数的特点:**

1. 执行构造函数代码之前,如果状态变量可以初始化为指定值;如果不初始化,则为默认值.
2. 合约的`abi`不包括构造函数代码或仅从构造函数调用的内部函数(该内部函数可以是`external`或者`public`但是如果仅从构造函数当中调用则在`abi`当中不会被编译.这样的目的是可以被派生合约更改该函数
3. 如果没有构造函数,合约将假定采用默认构造函数,它等效于`constructor() {}`
4. 构造函数可以使用内部`internal`参数(例如指向存储的指针),合约必须标记为`抽象合约`.因为参数不能赋值被外部赋值,而仅能通过派生的合约.
5. 基类构造函数如果有参数要被显示的声明在派生合约的构造函数当中,如果派生合约没有给所有的基类合约指定参数,那么该派生合约将是抽象的
**示例代码:**
`
pragma solidity ^0.8.0;

contract BaseFunction {
// 声明一个状态变量
uint x;
constructor(uint x) { x = x; }
}

// 在合约继承使用声明基类合约的构造参数
contract Base2 is BaseFunction(7) {
constructor() {}
}

// 在派生合约的构造函数当中对基类合约进行构造
contract Base3 is BaseFunction {
constructor(uint y) BaseFunction( y * y ) {}
}

// 继承基类合约,不在构造函数当中声明基类合约的构造函数,将其变为抽象合约
abstract contract ABase is BaseFunction {
constructor() {}
}
`

### 多继承

**`solidity`中多继承的特点:**

1. 基类在`is`后面的顺序从`最基类`到`最派生类`
**示例代码:**
`
contract X{}

contract A is X{}

// 这样书写多继承会编译报错.因为在编译器编译的时候会从右往左寻找构造函数,编译器会要求函数X重写函数A
// 构造函数将始终以线性化顺序执行,无论在继承合约的构造函数中提供其参数的顺序如何
contract B is A, X{}
`

**合约继承时会发生的错误:**

1. 函数和修改器同名
2. 函数和事件同名
3. 事件和修改器同名

### 抽象合约

**合约被声明为抽象的情况:**

1. 如果未实现合约中的至少一个函数,则需要将合约标记为`abstract`.实现了所有功能,合同也可能被标记为`abstract`
**示例代码:**
`
abstract contract Feline {
function utterance() public returns (bytes32);
}
`

**抽象合约作为基类并且能被构造的写法:**
`
abstract contract Feline {
function utterance() public returns (bytes32);
}

contract Cat is Feline {
// 这样就重写了一遍抽象合约当中的函数
function utterance() public pure returns (bytes32) { return "miaow"; }
}
`

2. 如果合约继承自抽象合约,并且没有通过重写来实现所有未实现的函数,需要标记为抽象`abstract`合约.

**抽象合约的特点:**

1. 抽象合约不能用一个无实现的函数重写一个实现了的虚函数

### 接口

**接口的一些特点:**

1. 类似抽象合约,不能实现任何函数
2. 接口无法继承其他合约,但是可以继承其他接口
3. 接口中的所有函数都要是`external`,合约里面的可以是`public`
4. 接口无法定义构造函数
5. 接口无法定义状态变量
6. 接口不可以声明修改器
7. 接口的特点,接口中的函数都会隐式标记为`virtual`.重写不需要`override`关键字.已重写的函数要再次重写要显式声明`virtual`

**接口的作用:**

接口限于合约`ABI`可以表示的内容,并且`ABI`和接口之间的转换不应该丢失任何信息
**示例代码:**
`
pragma solidity ^0.8.0;

interface Interface {
// 声明接口内容
enum TokenType { Fungible, NonFungible }
struct Coin { string obverse; string reverse; }
function transfer(address recipient, uint amount) external;
}
`

**接口继承重写的显、隐式声明:**
`
interface ParentA {
function tese() external returns (uint256);
}

interface ParentB {
function test() external returns (uint256);
}

// 声明一个接口,继承上诉两个接口.并且重新定义里面的test函数.
interface SubInterface is ParentA, ParentB {
// 必须重新定义 test 函数,以表示兼容父合约含义
function test() external override(ParentA, ParentB) returns (uint256);
}
`

posted @ 2022-08-10 18:08  俊king  阅读(47)  评论(0)    收藏  举报