智能合约的继承、接口、抽象

1,320 阅读3分钟

「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战

前言

面向对象的语言基本都有继承、接口、抽象的特性,对于智能合约来说,也是同样的。有着合约的继承、接口、抽象、重写,但其实又有些不一样,本文通过实例来分析一下,他们之间的具体概念。

继承

跟java不一样的是,合约里是多继承,即一个合约可以继承多个合约。当合约继承其他的合约时,只会在区块链上生成一个合约,所有相关的合约都会编译进这个合约,调用机制和写在一个合约上一致。

继承时,全局变量无法覆盖,如果出现可见的同名变量会编译错误

继承的关键字是is.

  // `is` 是继承的关键词. 子合约可以接受父合约所有非 private 的东西. 
contract Cat is Owned,Animal {
    //  `virtual` 表示函数可以被重写
    function destroy() virtual public {
        if (msg.sender == owner) selfdestruct(owner);//只有调用函数的人是部署者,才能执行自毁操作
    }
}

如果父合约有构造函数,那么子合约在继承的时候也是需要写上构造函数的。

继承是从右到左深度优先搜索来寻找同名函数(搜索的顺序是按 ”辈分“ 从小到大,而且继承多个合约时也要按着从右到左的顺序填上。

即按照最远原则处理

多继承是最远的向上继承,如1, 2, 3, 4, 4=>3 , 3=>2 , 2=>1 ,

Super:当前合约的上一层合约即所继承的合约。

接口

接口和抽象合约的作用很类似,但是它的每一个函数都没有实现,而且不可以作为其他合约的子合约,只能作为父合约被继承。

接口中所有的函数必须是external,且不包含构造函数和全局变量。接口的所有函数都会隐式标记为external,可以重写。多次重写的规则和多继承的规则和一般函数重写规则一致。

pragma solidity >=0.6.2 <0.9.0;
​
interface MyToken {
    enum TokenType { Fungible, NonFungible }
    struct Coin { string name; string total; }
    function transfer(address recipient, uint amount) external;
}

抽象合约

抽象合约需要声明为abstract。只要合约里有没有实现的函数,那么该合约会被视为抽象合约。

pragma solidity ^0.4.0;
contract Feline {
    function utterance() returns (bytes32);
}

如果子合约没有重写父合约中所有未完成的函数,那么子合约也需要标注abstract。

重写

父合约中被标记为virtual的非private函数可以在子合约中用override重写。

重写可以改变函数的标识符,规则如下:

  • 可见性只能单向从 external 更改为 public。
  • nonpayable 可以被 viewpure 覆盖。
  • view 可以被 pure 覆盖。
  • payable 不可被覆盖。

如果有多个父合约有相同定义的函数, override 关键字后必须指定所有父合约的名字,且这些父合约没有被继承链上的其他合约重写。

接口会自动作为 virtual

总结

对合约的抽象、接口、继承做了一定的说明。平时合约的编写可以根据不同的需要去做不同的处理,这也是要掌握的一个知识点。