Solidity学习::(6)智能合约继承

例子1:多继承下有重名函数,执行哪个函数的问题

contract owned {
    funtion owned() { owner =msg.sender;} //构造函数
    address owner;
}
contract mortal is owned { //mortal继承自owned
    function kill() {
        if(msg.sender==owner) selfdestruct(owned);
    }
}
contract Base1 is mortal {
    function kill() { /* do clean up 1*/   super.kill();}
}
contract Base2 is mortal {
    function kill() { /* do clean up 2*/   super.kill();}
}
contract Final is Base1,Base2{
}
  • Base1和Base2是mortal的派生合约
  • Final是Base2和Base1的派生合约
  • Final派生自两个合约(Base2和Base1),这两个父合约的顺序是有意义的,继承时会按照从左到右的顺序依次继承重写。
  • 合约中的函数都是虚函数,这意味着除非指定类名,否则调用的都是最后派生的函数。
  • 在例子中,Final先继承Base2,然后继承Base1,此时Base2中的kill函数将被Base1中的kill函数重写。
  • 所以,Final的继承序列为Final、Base2、Base1、mortal、owned
  • 当调用Final实例的kill函数时,将依次调用:Base2.kill()、Base1.kill()、mortal.kill()
  • 若Base1和Base2中的super.kill()换成mortal.kill(),则调用顺序为Base2.kill()、mortal.kill()

测试如下: 

(1)Base1和Base2中的super.kill()换成mortal.kill(),外部调用Final的kill方法,会跳过Base1的kill,只执行Base2的kill,最终执行mortal中的kill方法

pragma solidity ^0.4.0;
contract owned {
    function owned() { owner = msg.sender; }
    address owner;
}

contract mortal is owned {
    event mortalCalled(string);
    function kill() {
        mortalCalled("mortalCalled");
        if (msg.sender == owner) selfdestruct(owner);
    }
}


contract Base1 is mortal {
    event base1called(string);
    function kill() { /* do cleanup 1 */base1called("do cleanup 1"); mortal.kill(); }
}


contract Base2 is mortal {
    event base2called(string);
    function kill() { /* do cleanup 2 */base2called("do cleanup 2"); mortal.kill(); }
}


contract Final is Base1, Base2 { //外部调用Final的kill方法,会跳过Base1的kill,只执行Base2的kill
}

测试步骤:部署Final合约,触发kill方法,可以看到返回的日志如下,并没有触发Base1的事件

 

 

(2)Base1和Base2中都用super.kill(),则会依次调用Base2、Base1、mortal中的kill方法

pragma solidity ^0.4.0;
contract owned {
    function owned() { owner = msg.sender; }
    address owner;
}

contract mortal is owned {
    event mortalCalled(string);
    function kill() {
        mortalCalled("mortalCalled");
        if (msg.sender == owner) selfdestruct(owner);
    }
}


contract Base1 is mortal {
    event base1called(string);
    function kill() { /* do cleanup 1 */base1called("do cleanup 1"); super.kill(); }
}


contract Base2 is mortal {
    event base2called(string);
    function kill() { /* do cleanup 2 */base2called("do cleanup 2"); super.kill(); }
}


contract Final is Base1, Base2 { //外部调用Final的kill方法,会依次调用Base2、Base1、mortal中的kill方法
}


 例子2:(继承合约参数)

contract Base{
    uint x;
    function Base(uint _x) {x=_x;}
}
contract Derived is Base(7) {
    function Derived(uint _y) Base(_y *_y) {
    }
}
  • 派生合约的构造函数需要提供基类合约构造函数的所有参数,有两种方法
  • 第一种是上面  在继承列表中指定  is Base(7)
  • 另一种是在定义派生类的构造函数时,提供  Base (_y *_y),当基本合约(基类)的构造函数参数为变量时,应当用这种方式。
  • 当两种方式同时存在时,以第二种方式为准。

例子3:重写(抽象合约)

contract Feline{
    function utterance() returns (bytes32);    //抽象合约
}
contract Cat is Feline{
    function utterance() returns (bytes32) {return "miaow";}
}
  •  Solidity允许使用抽象合约。
  • 抽象合约是指一个合约只有函数声明而没有函数的具体实现,即函数的声明以“;”结束
  • 只要合约中有一个函数没有具体的实现,即使合约中其他函数已实现,这一抽象合约就不能被编译。

另外,在子类中允许重写函数,但不允许重写返回参数

pragma solidity ^0.4.0;

contract Base{
  function data() returns(uint){
    return 1;
  }
}

contract InheritOverride is Base{
  function data(uint){}
  function data() returns(uint){}
  //Override changes extended function signature
  //function data() returns(string){}
}

function data() returns(string){} 这一个重写了返回参数,会报错。 


关于访问父类变量:

pragma solidity ^0.4.0;

contract A{
  uint stateVar;

  function somePublicFun() public{}
  function someInternalFun() internal{}
  function somePrivateFun() private{}
}

contract AccessBaseContract is A{
  function call(){

    //访问父类的`public`方法
    somePublicFun();

    //访问父类的状态变量
    stateVar = 10;

    //访问父类的`internal`方法
    someInternalFun();

    //不能访问`private`
    //somePrivateFun();
  }
}

子类可以访问父类的public,internal权限控制变量或函数,不能访问private权限控制的变量和函数。在子类中可以直接访问状态变量,原因是因为状态变量默认是internal的。


继承不允许重名

 即父类和子类的修改器,方法,事件等不可以有相同的名字【不过在remix测试下并没有这个问题】,还有就是隐蔽的重名方式(getter访问器)见下面

pragma solidity ^0.4.0;

contract Base1{
  uint public data = 10;
}

contract Base2{
  function data() returns(uint){
    return 1;
  }
}

//一种隐蔽的情况,默认getter与函数名重名了也不行

转载自:http://me.tryblockchain.org/blockchain-solidity-inheritance.html


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值