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;
    // }
}  

Solidity 从入门到实战(五)_第1张图片

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)判断成功的时候

Solidity 从入门到实战(五)_第2张图片

当require(msg.sender == owner)判断不成功的时候
Solidity 从入门到实战(五)_第3张图片

案例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];
    }
}

新用户第一次注册
Solidity 从入门到实战(五)_第4张图片
新用户再次注册
Solidity 从入门到实战(五)_第5张图片

案例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;
   }
}

Solidity 从入门到实战(五)_第6张图片

案例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;
   }
}

Solidity 从入门到实战(五)_第7张图片

继承

无权限的继承

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();
    }
}

Solidity 从入门到实战(五)_第8张图片

有权限的继承

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()这个函数。

Solidity 从入门到实战(五)_第9张图片

如下图所示,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();
  }
    
}

Solidity 从入门到实战(五)_第10张图片

external能在合约外部调用

Solidity 从入门到实战(五)_第11张图片

那么,如何达到合约内部调用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();
  }
    
}

Solidity 从入门到实战(五)_第12张图片

//要想达到老师说的效果,选择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();
    }
}

Solidity 从入门到实战(五)_第13张图片

函数小结

  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();
    }
}

Solidity 从入门到实战(五)_第14张图片

案例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);
    }
}

Solidity 从入门到实战(五)_第15张图片

案例3

pragma solidity ^0.4.0;


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

Solidity 从入门到实战(五)_第16张图片

继承函数的重写

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();
    }
}

Solidity 从入门到实战(五)_第17张图片

多重继承

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;
    }
}

Solidity 从入门到实战(五)_第18张图片

合约销毁

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);
       }
   }
}

Solidity 从入门到实战(五)_第19张图片

你可能感兴趣的:(区块链,solidity,编程语言)