官方文檔翻譯 Solidity的語(yǔ)法介紹

合約

Solidity合約與面向?qū)ο笳Z(yǔ)言中的類(lèi)相似。它們包含可以修改這些變量的狀態(tài)變量和函數(shù)中的持久數(shù)據(jù)。在不同的合約(實(shí)例)上調(diào)用函數(shù)將執(zhí)行EVM函數(shù)調(diào)用,從而切換上下文以使?fàn)顟B(tài)變量不可訪(fǎng)問(wèn)。

創(chuàng)建合約

合約可以從“外部”或從Solidity合約創(chuàng)建。創(chuàng)建合約時(shí),其構(gòu)造函數(shù)(與合約名稱(chēng)相同的函數(shù))將執(zhí)行一次。

構(gòu)造函數(shù)是可選的。只允許一個(gè)構(gòu)造函數(shù),這意味著不支持重載。

從web3.js,即JavaScript API,這是按如下方式完成的:

// Need to specify some source including contract name for the data param below
var source = "contract CONTRACT_NAME { function CONTRACT_NAME(uint a, uint b) {} }";

// The json abi array generated by the compiler
var abiArray = [
    {
        "inputs":[
            {"name":"x","type":"uint256"},
            {"name":"y","type":"uint256"}
        ],
        "type":"constructor"
    },
    {
        "constant":true,
        "inputs":[],
        "name":"x",
        "outputs":[{"name":"","type":"bytes32"}],
        "type":"function"
    }
];

var MyContract_ = web3.eth.contract(source);
MyContract = web3.eth.contract(MyContract_.CONTRACT_NAME.info.abiDefinition);
// deploy new contract
var contractInstance = MyContract.new(
    10,
    11,
    {from: myAccount, gas: 1000000}
);

在內(nèi)部,構(gòu)造函數(shù)參數(shù)是在合約本身的代碼之后傳遞的,但如果使用web3.js,則不必關(guān)心這一點(diǎn)。

如果合約要?jiǎng)?chuàng)建另一個(gè)合約,則創(chuàng)建者必須知道所創(chuàng)建合約的源代碼(和二進(jìn)制文件)。這意味著循環(huán)創(chuàng)建依賴(lài)是不可能的。

pragma solidity ^0.4.0;

contract OwnedToken {
    // TokenCreator is a contract type that is defined below.
    // It is fine to reference it as long as it is not used
    // to create a new contract.
    TokenCreator creator;
    address owner;
    bytes32 name;

    // This is the constructor which registers the
    // creator and the assigned name.
    function OwnedToken(bytes32 _name) {
        // State variables are accessed via their name
        // and not via e.g. this.owner. This also applies
        // to functions and especially in the constructors,
        // you can only call them like that ("internally"),
        // because the contract itself does not exist yet.
        owner = msg.sender;
        // We do an explicit type conversion from `address`
        // to `TokenCreator` and assume that the type of
        // the calling contract is TokenCreator, there is
        // no real way to check that.
        creator = TokenCreator(msg.sender);
        name = _name;
    }

    function changeName(bytes32 newName) {
        // Only the creator can alter the name --
        // the comparison is possible since contracts
        // are implicitly convertible to addresses.
        if (msg.sender == address(creator))
            name = newName;
    }

    function transfer(address newOwner) {
        // Only the current owner can transfer the token.
        if (msg.sender != owner) return;
        // We also want to ask the creator if the transfer
        // is fine. Note that this calls a function of the
        // contract defined below. If the call fails (e.g.
        // due to out-of-gas), the execution here stops
        // immediately.
        if (creator.isTokenTransferOK(owner, newOwner))
            owner = newOwner;
    }
}

contract TokenCreator {
    function createToken(bytes32 name)
       returns (OwnedToken tokenAddress)
    {
        // Create a new Token contract and return its address.
        // From the JavaScript side, the return type is simply
        // "address", as this is the closest type available in
        // the ABI.
        return new OwnedToken(name);
    }

    function changeName(OwnedToken tokenAddress, bytes32 name) {
        // Again, the external type of "tokenAddress" is
        // simply "address".
        tokenAddress.changeName(name);
    }

    function isTokenTransferOK(
        address currentOwner,
        address newOwner
    ) returns (bool ok) {
        // Check some arbitrary condition.
        address tokenAddress = msg.sender;
        return (keccak256(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff);
    }
}

可見(jiàn)標(biāo)識(shí)的及getter方法

由于Solidity知道兩種函數(shù)調(diào)用(不產(chǎn)生實(shí)際EVM調(diào)用的內(nèi)部函數(shù)(也稱(chēng)為“消息調(diào)用”)和外部函數(shù)調(diào)用),函數(shù)和狀態(tài)變量有四種類(lèi)型的可見(jiàn)性。

函數(shù)可以被指定為external, public, internalprivate,默認(rèn)為public。對(duì)于狀態(tài)變量,external是不被允許的,默認(rèn)是internal

external
external函數(shù)是合約接口的一部分,這意味著可以從其他合約和交易中調(diào)用它們。external函數(shù)f不能在內(nèi)部調(diào)用(即f()不起作用,但this.f()起作用)。external函數(shù)在接收大量數(shù)據(jù)時(shí)有時(shí)更高效。
public
public函數(shù)是合約接口的一部分,可以在內(nèi)部或通過(guò)消息調(diào)用。對(duì)于公共狀態(tài)變量,會(huì)生成一個(gè)自動(dòng)填充getter方法(見(jiàn)下文)。
internal
這些函數(shù)和狀態(tài)變量只能在內(nèi)部進(jìn)行訪(fǎng)問(wèn)(即從當(dāng)前合約或從中得出的合同),而不使用this
private
private函數(shù)和狀態(tài)變量?jī)H對(duì)它們定義的合約而不是衍生合約中可見(jiàn)。

注意:所有外部觀察者都可以看到合約內(nèi)的所有內(nèi)容。使用private修飾只會(huì)阻止其他合約訪(fǎng)問(wèn)和修改信息,但在區(qū)塊鏈之外,整個(gè)世界仍然可以看到它。

可見(jiàn)性說(shuō)明符在狀態(tài)變量的類(lèi)型之后以及函數(shù)的參數(shù)列表和返回參數(shù)列表之間給出。

pragma solidity ^0.4.0;

contract C {
    function f(uint a) private returns (uint b) { return a + 1; }
    function setData(uint a) internal { data = a; }
    uint public data;
}

在下面的例子中,D可以調(diào)用c.getData()來(lái)檢索狀態(tài)存儲(chǔ)中的數(shù)據(jù)值,但不能調(diào)用f。合約E來(lái)自C,因此可以調(diào)用compute。

// This will not compile

pragma solidity ^0.4.0;

contract C {
    uint private data;

    function f(uint a) private returns(uint b) { return a + 1; }
    function setData(uint a) { data = a; }
    function getData() public returns(uint) { return data; }
    function compute(uint a, uint b) internal returns (uint) { return a+b; }
}


contract D {
    function readData() {
        C c = new C();
        uint local = c.f(7); // error: member "f" is not visible
        c.setData(3);
        local = c.getData();
        local = c.compute(3, 5); // error: member "compute" is not visible
    }
}
contract E is C {
    function g() {
        C c = new C();
        uint val = compute(3, 5);  // acces to internal member (from derivated to parent contract)
    }
}

Getter函數(shù)

編譯器自動(dòng)為所有公共狀態(tài)變量創(chuàng)建getter函數(shù)。對(duì)于下面給出的合約,編譯器將生成一個(gè)名為data的函數(shù),該函數(shù)不接受任何參數(shù)并返回uint,狀態(tài)變量數(shù)據(jù)的data。狀態(tài)變量的初始化可以在聲明中完成。

pragma solidity ^0.4.0;

contract C {
    uint public data = 42;
}


contract Caller {
    C c = new C();
    function f() {
        uint local = c.data();
    }
}

getter函數(shù)具有外部可見(jiàn)性。如果符號(hào)是在內(nèi)部訪(fǎng)問(wèn)的(即沒(méi)有this),則它被評(píng)估為一個(gè)狀態(tài)變量。如果它被外部訪(fǎng)問(wèn)(即用this),它被作為一個(gè)函數(shù)來(lái)評(píng)估。

pragma solidity ^0.4.0;

contract C {
    uint public data;
    function x() {
        data = 3; // internal access
        uint val = this.data(); // external access
    }
}

下一個(gè)例子有點(diǎn)復(fù)雜:

pragma solidity ^0.4.0;

contract Complex {
    struct Data {
        uint a;
        bytes3 b;
        mapping (uint => uint) map;
    }
    mapping (uint => mapping(bool => Data[])) public data;
}

它將生成以下形式的函數(shù):

function data(uint arg1, bool arg2, uint arg3) returns (uint a, bytes3 b) {
    a = data[arg1][arg2][arg3].a;
    b = data[arg1][arg2][arg3].b;
}

請(qǐng)注意,結(jié)構(gòu)中的映射被省略,因?yàn)闆](méi)有提供映射關(guān)鍵的好方法。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文翻譯自:https://github.com/ConsenSys/smart-contract-best-pr...
    tolak閱讀 5,251評(píng)論 4 21
  • 可見(jiàn)性和訪(fǎng)問(wèn)限制符(Visibility And Accessors) 因?yàn)镾olidity可以理解兩種函數(shù)調(diào)用(...
    yuyangray閱讀 7,076評(píng)論 0 2
  • 原文鏈接date:20170710 Solidity中合約的概念和其他面向?qū)ο笳Z(yǔ)言中的類(lèi)差不多。他們都有狀態(tài)變量來(lái)...
    gaoer1938閱讀 1,110評(píng)論 0 0
  • 上午 : 早上來(lái)了,開(kāi)始做游戲,找朋友的游戲,石頭剪刀布,定輸贏,贏的做龍頭,輸?shù)淖鑫舶?,最后所有的人排成一條長(zhǎng)長(zhǎng)...
    窗戶(hù)邊的小余閱讀 670評(píng)論 0 1
  • 我曾在春夜里拄著一束光 漫步在村莊的小徑上 不去想該去哪 只是聽(tīng)著溪流的破碎 享受這份恬然 我曾在夏夜里追著無(wú)數(shù)光...
    晴天ol閱讀 143評(píng)論 0 0

友情鏈接更多精彩內(nèi)容