Solidity 从入门到实战(五)

Solidity 从入门到实战(五)

注意:本专栏主要参考于https://www.bilibili.com/video/BV1St411a7Pk?p=11&spm_id_from=pageDriver的学习笔记以及https://blog.csdn.net/weixin_45067603/article/details/105751748

构造函数

  1. 在合约部署时自动调用一次,而且只能调用这一次
  2. 使用方法有两种:
    ①新式(推荐):constructor(参数列表) {}
    ②旧式:function 合约名(参数列表) {}
    如果传入参数,那么部署时也需要输入参数
  3. 作用:可以用来声明,赋值变量(常用于获取合约调用者的地址)等等
  4. 一个程序中可以写多个合约
//这里使用0.4.16版本会出现编译错误,因为构造函数与编译器版本不匹配出错,这里选择使用0.5.0
pragma solidity ^0.5.0;

contract gouzao2Test{
       address public owner;
       
       uint public a;
       constructor() public{
           
           //a=100;
           owner = msg.sender;//获取合约调用者的地址
       }
   }
contract gouzaoTest{
    uint public a; //一个合约只能有零个或一个构造函数
    //构造函数在一部署合约的时候就回被执行
    //function gouzaoTest(){
    //    a=100;
    //}
    //构造函数可以有参数
    // function gouzaoTest(uint _a,uint _b) {
    //   a=_a;
    // }
}  

在这里插入图片描述

modifier函数

  1. 应用场景:作判断,赋值等等
  2. 主要作用:使得代码可以重用
案例1
pragma solidity ^0.5.0;

contract modifierTest{
       address public owner;
      
       uint public num =0;
       
       constructor()public {
       //合约部署者的地址
           owner = msg.sender;
          
       }
       //定义modifer
       modifier OnlyOwner{
       //判断当前登录者地址是否是合约的部署者,如果是的话,执行下面的语句,否则,进行回滚操作
           require(msg.sender == owner);
           
           _;

       }
       //附加 modifer,先执行 require(msg.sender == owner),判断成功后,就会执行num = _num;
       function changeIt(uint  _num)public OnlyOwner {
           num = _num;
       }
       
       
}   

当require(msg.sender == owner)判断成功的时候

在这里插入图片描述

当require(msg.sender == owner)判断不成功的时候
在这里插入图片描述

案例2

对之前一个注册的案例进行改造,因为存在一个账户可以重复注册多次的问题

pragma solidity ^0.4.16;
contract mappingTest{
    // 定义mapping idmapping 代表地址==》id映射到了一起,namemapping代表id==>名字映射到了一起
    mapping(address => uint) idmapping;
    mapping(uint => string) namemapping;
    //定义注册的总量
    uint public sum =0;
    
    //定义modifer
    modifier control{
    //如果当前idmapping[msg.sender]==0,说明该用户是个新用户,允许进行接下来的操作
        require(idmapping[msg.sender]==0);
        _;
    }
    //注册函数
    function register(string name) control{
       //获取当前合约的调用者地址
        address account = msg.sender;
        sum++;
        //将合约的调用者的地址与注册总量id联系到一起
        idmapping[account]= sum;
        //将当前用户的id与用户的姓名绑定到一起
        namemapping[sum] =name;
    }
    //通过地址获取到用户绑定的id值
    function getIdByAddress(address are) view public returns(uint){
        return idmapping[are];
    }
    //通过id值获取到它绑定的姓名
    function gerNameById(uint id) view public returns(string){
        return namemapping[id];
    }
}

新用户第一次注册
在这里插入图片描述
新用户再次注册
在这里插入图片描述

案例3

modifer可以有参数

pragma solidity ^0.4.16;
contract mappingTest2{
   uint public level =9;
   string public name;
   uint public DNA;
   
   //定义modifier,可以有参数,提高了代码的重用性和扩展性
   modifier contrlLevel(uint needLevel){
       
      require(level >= needLevel);
      _;
   }
   
   function changeName() contrlLevel(2){
       name ="吴彦祖";
   }
   
   function changeDNA() contrlLevel(10){
       DNA = 999;
   }
}

在这里插入图片描述

案例4

多个modifier的执行顺序

pragma solidity ^0.4.16;
contract mulmodifierTest{
   uint public a =0;
   modifier mod1{
       a=1;
       _; //将mod2嵌入进来
       a=2;
   }
   modifier mod2{
       a=3;
       _;
       a=4;
   }
   //执行顺序:a=1,a=3,a=100,a=4,a=2;
   function test() mod1 mod2{
       
       a=100;
   }
}

在这里插入图片描述

继承

无权限的继承
pragma solidity ^0.4.16;

contract grandfarther{
    uint public gudong =2000;
    
    function zhongdi() public returns(string){
        return "zhongdi";
    }
}
contract father is grandfarther{
  uint public money =10000;
  
  function dahan() public returns(string){
      return  "dahan";
  }
}
//son继承了father,father继承了grandfarther,son就可以继承他们的所有属性和函数
contract son is father{
    
    function getMoney() public view returns(uint){
        return money;
    }
    
    function getGudong()public view returns(uint){
        return gudong;
    }
    
    function test01() public view returns(string){
        return zhongdi();
    }
    
    function test02() public view returns(string){
        return dahan();
    }
}

在这里插入图片描述

有权限的继承
pragma solidity ^0.4.16;
contract father {
//1. uint money=10000;不加任何修饰符,可以被继承
//2. uint public money=10000;加上public,可以被继承
//3. uint internal money=10000;加上internal,可以被继承
//4. uint external money=10000;编译报错,没有external属性修饰符

  uint private money =10000;//编译报错,只有父亲拥有改属性,不能被继承
  
  function dahan() public returns(string){
      return  "dahan";
  }
}

contract son is father{
    
    function getMoney() public view returns(uint){
        return money;
    }
    
}
函数继承
pragma solidity ^0.4.16;


contract father {
 //public、internal、external 函数都可以被继承,external函数继承方式不太相同,如下面的代码所示
 //private智能合约自己独立使用,不能够被继承
  function dahan() public pure  returns(string){
      return  "dahan";
  }
}

contract son is father{
    
  function test() public  pure returns(string){
     return dahan();
  }
    
}
pragma solidity ^0.4.16;


contract father {
 
  function dahan() external pure  returns(string){
      return  "dahan";
  }
}

contract son is father{
    
  function test() public  pure returns(string){
  //external 函数继承方式
      this.dahan();
  }
    
}

注意:

  1. internal只能在合约内部调用,合约外部不行;
  2. external只能在合约外部调用,合约内部不行;
    所谓外部和内部,以remix举例,在内部就是指合约内部可以调用这个函数,在外部就是指合约部署之后可以在旁侧看到这个函数的按钮。
    如下图所示,farther外部只显示test1(),但是可以调用dahan()这个函数。

在这里插入图片描述

如下图所示,external在合约内部按照下图所示方式调用会出现错误

pragma solidity ^0.4.16;


contract father {
 
  function dahan() external pure  returns(string){
      return  "dahan";
  }
  //external修饰的函数不能够在内部调用
//   function test1() public view {
//       dahan();
//   }
}

contract son is father{
    
    //external修饰的函数不能够在被继承的合约内部调用
  function test() public  view returns(string){
     return dahan();
  }
    
}

在这里插入图片描述

external能在合约外部调用

在这里插入图片描述

那么,如何达到合约内部调用external函数的效果呢?有两种方式,本质上是通过间接通过外部合约调用

  1. 使用 this.函数名 调用
  2. 再声明一个合约,在新的合约内部创建或者引用该合约即可
//要想达到老师说的效果,选择0.4.0版本,编译器选择0.4.23版本
pragma solidity ^0.4.0;


contract father {
 
  function dahan() external pure  returns(string){
      return  "dahan";
  }
  //间接的在合约内部调用,输入this.
   function test1() public view  {
       this.dahan();
   }
}

contract son is father{
    
  function test() public  view returns(string){
      this.dahan();
  }
    
}

在这里插入图片描述

//要想达到老师说的效果,选择0.4.0版本,编译器选择0.4.23版本
pragma solidity ^0.4.0;


contract father {
 
  function dahan() external  pure  returns(string){
      return  "dahan";
  }
  function test1() public view returns(string) {
      return  this.dahan();
  }
}

// contract son is father{
    
//   function test() public  view returns(string){
//       this.dahan();
//   }
    
// }
//第二种调用方式,在另一个合约内部创建或引用合约的地址“地址.”来调用
contract externalTest {
    father f =new father();
    function externalTestIt() public view returns(string){
         return  f.dahan();
    }
}

在这里插入图片描述

函数小结
  1. private不能够被继承、不能够在外部调用、可以在内部被调用;
  2. internal 可以在内部被调用,不能在外部调用、可以被继承;
  3. external 不能在内部调用,只能在外部调用,如果强行调用,通过"地址."方式调用;
  4. public权限最大,可以在外部和内部调用,可以被继承;
  5. pure 不会读取全局变量,更不会修改全局变量,一个固定的输入就会有一个固定的输出,不消耗gas;
  6. constant 在函数中,与view相同,在全局变量中,只用于byte1–byte32,uint,int,string代表数据不能够被修改;
  7. view 只读取全局变量的值,不修改值,不消耗gas;
  8. payable 转账的时候必须要加的关键字
  9. 函数可以有多个返回值
getter使用
案例1
pragma solidity ^0.4.0;
//1.public修饰符默认生成get方法,供我们外部调用
contract getter{
    uint public num =100;
    //2.它等价于这个函数,当我们写了这个函数的时候,默认的函数就会消失
    //3. 默认生成的get函数是external权限的,不能够在合约的内部调用
    function num() external view returns(uint){
        return num;
    }
    
    function test(){
        this.num();
    }
}

在这里插入图片描述

案例2
pragma solidity ^0.4.0;


contract getter{
    uint public num =100;
    
    mapping(uint =>string) public map;
    //mapping类型很特殊,默认的会生成下面这个函数,
    //function map(uint key)external returns(string){
    
    //}
    function test(){
        this.num();
    }
    function test2(){
        map[2] ="吴彦祖";
        
    }
    function test3()returns(string){
        return this.map(2);
    }
}

在这里插入图片描述

案例3
pragma solidity ^0.4.0;


contract getter{
    mapping(uint =>mapping(uint =>mapping(uint =>string))) public map;
    
    function test(){
        map[0][1][2]= "吴彦祖";
        
    }
    
}

在这里插入图片描述

继承函数的重写
pragma solidity ^0.4.0;


contract father{
    uint public money =10000;
    
    function dahan() returns(string){
        return "打小鼾";
    }
}

contract son is father {
//覆盖掉父亲的值
    uint public money =200000;
    
    function getMoney()returns(uint){
        return  money;
    }
    
    function dahan()returns(string){
        return "打大鼾";
    }
    
    function test() view returns(string){
        //覆盖掉父亲的方法
        return dahan();
    }
}

在这里插入图片描述

多重继承
pragma solidity ^0.4.0;


contract father{
    uint public money =10000;
    
    function test() returns(string){
        return "A";
    }
}
contract mother{
    uint public heignt =180;
    function test()returns(string){
        return "B";
    }
}
contract son is father,mother { //按照father,monther的顺序进行继承
    uint public money =200000;
    uint public heignt =190; //重写属性值
    
    function test() returns(string){ //重写方法
        return "son";
    }
    function getHeight() returns(uint){
        return heignt;
    }
}

在这里插入图片描述

合约销毁
pragma solidity ^0.4.0;


contract destruct{
   address owner;
   
   uint public money =0;
   constructor(){
       owner = msg.sender;
   }
   function increment(){
       money +=10;
   }
   
   function kill(){
       if(msg.sender == owner){
       //如果是当前合约的调用者,进行销毁合约
           selfdestruct(owner);
       }
   }
}

在这里插入图片描述

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟逆袭之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值