函數定義與訪問控制
學習目標
掌握 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;
}
}
主題測試文章,只做測試使用。發佈者:Walker,轉轉請注明出處:https://walker-learn.xyz/archives/7491