← 返回
Web3与WASM 2026.03.09

函數定義與訪問控制

Web3与WASM

學習目標

掌握 Solidity 函數定義、可見性修飾符、交易屬性、modifier 和構造函數。


函數定義

一般形式

function fname([參數]) [可見性][交易屬性][modifier...] returns(返回值) { ... }
  • 函數簽名fname([參數]) —— 唯一標識一個函數
  • 返回值returns(返回值) —— 聲明函數返回的類型

函數可見性

Solidity 提供四種可見性修飾符,控制函數的調用範圍:

修飾符說明
public完全可見,內部和外部都能調用
private僅本合約可見,子合約也不能訪問
internal本合約和子合約可見(類似 Java 的 protected)
external僅外部調用(通過 this 在內部調用會產生新的 message)

注意:變量默認 internal,函數默認 public。這與其他編程語言不同!

可見性示意圖

A 合約
├── private   pri()    → 僅 A 內部
├── internal  inter()  → A 內部 + 子合約 B
├── public    pub()    → 全部可見    ←── C 合約可調用
└── external  ext()    → 僅外部      ←── C 合約可調用

B is A(繼承 A)
├── inter()  可訪問
└── pub()    可訪問

交易屬性

交易屬性決定函數是否修改鏈上狀態,直接影響 gas 消耗:

屬性說明
默認(無修飾)寫操作,全網廣播,共識確認,消耗 gas
view只讀操作,讀取合約狀態,不消耗 gas(外部調用時)
pure純函數,與合約狀態無關,只依賴輸入參數

完整示例

// SPDX-License-Identifier: MIT
pragma solidity >=0.8.2 <0.9.0;

contract NumberStorage {
    uint public x;

    // 寫操作(默認):修改狀態,消耗 gas
    function setX(uint px) public {
        x = px;
    }

    // view:只讀狀態
    function getX() public view returns(uint) {
        return x;
    }

    // pure:與狀態無關的純計算
    function add(uint a, uint b) private pure returns(uint) {
        return a + b;
    }
}

函數修飾器(Modifier)

Modifier 類似 AOP(面向切面編程),常用於訪問控制和前置條件檢查。

  • require / revert 進行條件檢查,不滿足時回滾交易
  • _; 表示執行被修飾的函數體
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract NumberModifier {
    uint private number;

    modifier nonZero() {
        require(number != 0, "Number is zero and cannot be processed.");
        _;
    }

    function doubleNumber() public nonZero {
        number *= 2;
    }

    function resetNumber() public {
        number = 0;
    }
}

構造函數(Constructor)

構造函數在合約部署時調用一次,常用於初始化狀態變量。msg.sender 是合約部署者的地址。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Constructor {
    address public owner;
    uint public x;

    constructor(uint _x) {
        owner = msg.sender;
        x = _x;
    }
}

綜合實例:Ownable 合約

結合構造函數、modifier 和可見性控制,實現一個「僅擁有者可操作」的權限管理合約:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Ownable {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "not owner");
        _;
    }

    function setOwner(address _newOwner) external onlyOwner {
        require(_newOwner != address(0), "invalid address");
        owner = _newOwner;
    }
}

Counter 合約示例

一個簡單的計數器合約,展示 external 可見性的使用:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

contract Counter {
    uint public count;

    function inc() external {
        count += 1;
    }

    function dec() external {
        count -= 1;
    }
}