Solidity语言学习——(五)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/The_Reader/article/details/83113207

控制语句

solidity中所支持的控制语句:

if else , for , while,do while,三目运算符。不支持switch语句。

直接通过案例学:


// for
contract For {
    // 等差数列求和
    function getSum(uint n, uint x) public returns(uint sum) {
        for (uint index = 0; index < n; index+=x) {
            sum += index;
            if (index > 50) {
                break;
            }
        }
    }
}

contract While {
    function getSum (uint n, uint x) view public returns(uint sum) {
        uint i = 0;
        while(i < n) {
            sum += i;
            i += x;
        }
    }
}

contract DoWhile {
    function getSum(uint n, uint x) view public returns (uint sum) {
        uint i = 0;
        do {
            sum += i;
            i += x;
        }while(i < n);
    }
}

contract condition {
    // 条件控制
    function getT(uint x,uint y) view public returns(string) {
        return mulmod(x, y, 2) == 0 ? "偶数":"奇数";
    }
}

结果为:

 合约for

合约While

 合约do-while

 合约condition

 全局单位

货币单位:

wei:1wei

kwei:1000wei

gwei:10的6次方wei

mwei:10的9次方位

mircroether:10的12次方位

millierther(finnry):10的15次方位

ether:10的18次方位

案例:

// 货币单位
contract Money {
    uint a = 1 ether;
    uint b = 1 finney;

    function compare() view public returns(bool) {
        if (a == 1000 * b) {
            return true;
        }
        return false;
    }

}

结果为:

 

时间单位:

Seconds,minutes,hours,days,weeks,years。

案例:


// 时间单位 
contract tm {
    uint a = 1;
    uint b = a * 1 seconds;
    // seconds,minutes,hours,days,weeks, years 时间单位
    function getTime() view public returns(uint) {
        return b;
    }
}

结果为:

 

内建的全局变量

在solidity中,内建的全局变量,可以在合约脚本的任何地方使用。

  1. 包含msg的所有 :msg.sender(发送者地址),msg.value(发送给合约的以太币,默认单位时位),msg.gas(剩余gas),msg.data(调用数据)。
  2. 包含this的Balance(余额)
  3. 包含Tx的origin(交易发送者地址),gasprice(gas价格)。
  4. Now,***.now(当前时间)
  5. Block属性:Number(区块号),Difficulty(难易程度),Coinbase(矿工地址),Timestamp(时间戳),Gaslimt(当前区块的gaslimit),Blockhash(num)(给定区块的hash值,只支持最近256个区块)。

函数

solidity本身呢也是一门函数型语言,函数可以做参数,变量,返回值。

函数属于值类型,支持多返回值。

调用方式:

        内部调用:不copy数据,采用EVM跳转调用,所有能够直接使用和更改上下文的数据,所以在数据传递时非常的高效,

对合约内的函数,引入的库函数和从父合约中继承的函数都可以进行内部调用。

        外部调用:使用外部调用得方式,进行调用,函数的所有参数都会先拷贝到内存中,使用external。

案例:

pragma solidity ^0.4.18;

contract Func {
    uint x = 100;
    uint y = 200;
    function add() returns(uint) {
        return x + y;
    }

    // 内部调用 
    function display() public view returns(uint) {
        return add();
    }

    // 多返回值
    mapping(addres => uint) balances;
    function insert() public {
        balances[0xDF5EB3d771DACaD2dA5E8Cb5ae4ccc16BF6D514E] = 100;
    }

    function get() public view returns(address, uint) {
        return(0xDF5EB3d771DACaD2dA5E8Cb5ae4ccc16BF6D514E, balances[0xDF5EB3d771DACaD2dA5E8Cb5ae4ccc16BF6D514E]);
    }
}

 结果为:

 函数定义类型:

view :只读,不改变合约的内部状态

注: 1.写入状态变量,2.触发事件 3.创建合约,4.使用自毁函数,5.发送以太币,6.调用任何一个没有被view或者pure的函数,7.底层的调用。

pure:不会修改合约的状态,也不会读合约的状态,基本上就是费用。所以用它读取与合约状态无关的数据。

与view相比,pure的限制还包括更多的内容:

1.不能读取状态变量,2.不能访问this.balance或者address.balance,3.不能访问block.msg的大多数成员(可以访问msg.sig,msg.data),4.调用任何一个没有被标记为pure的函数。

 注:如果需要更改状态变量,就不要使用view不然会出现不会报错,但会出警告这样的。

特殊函数类型

1.回退函数:在每个合约中都有一个没名字的函数,该函数没有名字,没参数,没有返回值,这个就是回退函数。

作用:给合约发送eth时也会调用,需要注意的是,如果合约没有定义回调函数的话,接收ether会触发异常。

如果回调函数要接受ether,必须payable修改饰符。

2.自毁函数:自会函数可以摧毁当前合约,如果合约中含有以太币,则会将以太币转移到指定的地址。如果合约在被自毁之后还有人向合约中发送eth,则这些以太币就会消失,无法赎回。

3.常函数:不会修改区块链中的任何状态,没有强制的规定,但是会给警告。关键字为:constant
4.访问器:编译器为自动为所有的public状态变量创建访问器。访问函数具有外部可见性,如果通过内部方式访问,可以直接当成一个变量,但如果通过外部方式进行访问,比如通过this,那么必须通过函数的方式调用。注:只要使用this,它就变成了外部的一个东西。

// 访问器
contract C {
    uint public c = 10;
    function accessInternal() returns(uint) {
        return c; // 内部方式访问
    }

    // 通过external(外部)的方式访问
    function accessExternal() returns(uint) {
        return this.c();
    }
}

// 调用其它合约的访问器
contract D {
    C c = new C(); // 实例化其它合约对象

    function getData() returns(uint) {
        return c.c();
    }
}

 结果为:

    1. 其它内置函数
    2. 加密函数
      1. ecrecover(hash, v, r, s)
      2. ripemd160(x)
      3. sha3(x)
      4. sha256(x)
      5. keccak256(x)
      6. Solidity中的加密实际上调用的是以太中的加密函数
      7. 数据函数
        1. addmod(x, y, k):x+y对k取余
        2. mulmod(x, y, k):x * y 对k 取余
    3. 函数修改器(modifier)
      1. 修改器的作用是在函数执行前检查某种前置条件是否满足
      2. 修改器是一种合约的属性,可以被继承也可以被派生的合约重写。
      3. 一个函数可以有多个修改器,其间采用空格分开,而修改器的生效顺序与定义顺序一样。
      4. 修改器中的"_",必须有,没有的话就不叫修改器。

回退函数

调用一个不存在的函数

pragma solidity ^0.4.18;


// 1. 实现回退函数
// 调用一个不存在的函数
contract ExecuteFallback {
    // 新建一个事件,把调用的数据打印出来
    event FallbackCalled(bytes data);

    // fallback函数
    function() {
        // 调用回退事件
        FallbackCalled(msg.data);
    }


    // existFunc事件
    event ExistFuncCalled(bytes data, uint256 para);
    // 写一个已经存在的函数
    function existFunc(uint256 para) {
        ExistFuncCalled(msg.data, para);
    }

    // 调用一个已经存在的函数
    function callExistFunc() {
        bytes4 funcIdentifier = bytes4(keccak256("existFunc(uint256)"));
        this.call(funcIdentifier, uint256(1));
    }

    // 调用一个不存在的函数
    function callNotExistFunc() {
        bytes4 funcIdentifier = bytes4(keccak256("functionNotExist"));
        this.call(funcIdentifier)
    }

    // 数据验证
     function getExist() view returns(bytes32) {
        return keccak256("existFunc(uint256)");
    }
    
    function getNotExist() view returns(bytes32) {
        return keccak256("functionNotExist");
    }
}

 自毁函数

// 2. 实现自毁合约
contract SelfDestructionContract {
    // 权限限制
    modifier ownerRestricted {
        require(owner == msg.sender);
        _;
    }
    // 一般来说,能够销毁合约的人必须是合约的所有者
    address public owner; // 所有人
    string public someValue; // 值的设置
    // 构造函数
    function SelfDestructionContract() {
        owner = msg.sender;
    }

    

    // 设置一个值
    function setSomeValue(string value) {
        someValue = value;
    }

    // 调用自毁函数
    function destroyContract() ownerRestricted {
        // 自毁函数
        selfdestruct(owner);
    }
}

 函数的可见性与权限:

      内部函数:internal:不能够在当前合约的上下文环境之外执行,只能在当前合约内进行调用,比如当前的代码块,内部的库函数,继承的合约中。在外部调用内部函数会报错。

  // 内部函数
    function internalFun() view internal returns(string){
        return "internal func";
    }
    // 在当前合约内进行内部函数的调用
    function callInternalFunc() view public returns(string) {
        return internalFun();
    }

      外部函数:external:可以用从外部函数调用的参数,或者有外部函数调用返回,还可以通过其他合约进行调用,如果时this调用,那么都是在通过external的方式进行调用,不能在内部去调用一个外部函数。

      公有函数:public:在哪都可以调用,public类型的状态变量或者函数,会自动创建一个访问器。

      私有函数:private:只能在当前合约中进行访问,不能通过继承进行访问。

案例:

contract Chmod {
    // 内部函数
    function internalFun() view internal returns(string){
        return "internal func";
    }
    // 在当前合约内进行内部函数的调用
    function callInternalFunc() view public returns(string) {
        return internalFun();
    }

    // 外部函数
    function externalFunc() view external returns(string) {
        return "external func";
    }

    // 在当前合约中进行外部函数的调用 会报错,只能通过this进行调用 
    function callExternalFunc() view public returns(string) {
        return externalFunc();
    }

    // 私有函数
    function privateFunc() view private returns(string) {
        return "private func";
    }

    // 在当前合约内调用私有函数
    function callPrivateFunc() view public returns(string) {
        return  privateFunc();
    }

    // 公有函数
    function publicFunc() view public returns(string) {
        return "public func";
    }

    // 在内部调用公有函数
    function callPublicFunc() view public returns(string) {
        return publicFunc();
    }
}
// 外部调用 ,相当于在当前合约的上下文之外进行调用
contract externalCall {
    Chmod ch = new Chmod(); //合约实例
    // 外部调用内部函数
    function callInternalFunc() view public returns(string) {
        //return ch.internalFun(); 在外部调用内部函数直接报错
    }

    // 外部调用外部函数
    function callExternalFunc() view public returns(string) {
        return ch.externalFunc();
    }

    // 在外部调用私有函数
    function callPrivateFunc() view public returns(string) {
    //    return ch.privateFunc(); 报错,私有函数在外部不可见
    }

    // 外部调用公有函数
    function callPublicFunc() view public returns(string) {
        return ch.publicFunc();
    }
}

// 通过继承调用
contract child is Chmod {
    // 在继承中调用内部函数
    function callInternal() view public returns(string) {
        return internalFun();
    }

    // 在继承中调用外部函数
    function callExternalFunc() view public returns(string) {
        return externalFunc(); // 还是需要通过this进行调用
    }

    // 在继承中调用私有函数
    function callPrivateFunc() view public returns(string) {
        return privateFunc();
    }

    // 在继承中调用公有函数
    function callPublicFunc() view public returns(string) {
        return publicFunc();
    }
}

猜你喜欢

转载自blog.csdn.net/The_Reader/article/details/83113207