注意:本专栏主要参考于https://www.bilibili.com/video/BV1St411a7Pk?p=11&spm_id_from=pageDriver的学习笔记以及https://blog.csdn.net/weixin_45067603/article/details/105751748
- 在合约部署时自动调用一次,而且只能调用这一次
- 使用方法有两种:
①新式(推荐):constructor(参数列表) {}
②旧式:function 合约名(参数列表) {}
如果传入参数,那么部署时也需要输入参数- 作用:可以用来声明,赋值变量(常用于获取合约调用者的地址)等等
- 一个程序中可以写多个合约
//这里使用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;
// }
}
- 应用场景:作判断,赋值等等
- 主要作用:使得代码可以重用
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)判断成功的时候
对之前一个注册的案例进行改造,因为存在一个账户可以重复注册多次的问题
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];
}
}
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;
}
}
多个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();
}
}
注意:
- internal只能在合约内部调用,合约外部不行;
- 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函数的效果呢?有两种方式,本质上是通过间接通过外部合约调用
- 使用 this.函数名 调用
- 再声明一个合约,在新的合约内部创建或者引用该合约即可
//要想达到老师说的效果,选择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();
}
}
- private不能够被继承、不能够在外部调用、可以在内部被调用;
- internal 可以在内部被调用,不能在外部调用、可以被继承;
- external 不能在内部调用,只能在外部调用,如果强行调用,通过"地址."方式调用;
- public权限最大,可以在外部和内部调用,可以被继承;
- pure 不会读取全局变量,更不会修改全局变量,一个固定的输入就会有一个固定的输出,不消耗gas;
- constant 在函数中,与view相同,在全局变量中,只用于byte1–byte32,uint,int,string代表数据不能够被修改;
- view 只读取全局变量的值,不修改值,不消耗gas;
- payable 转账的时候必须要加的关键字
- 函数可以有多个返回值
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();
}
}
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);
}
}
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);
}
}
}