本文将探讨如何在 Rust 和 Solana 中实现类似 Solidity 的函数可见性,以及如何通过模块化复用来模拟“继承”。
本文将探讨如何在 Rust 和 Solana 中实现类似 Solidity 的函数可见性,以及如何通过模块化复用来模拟“继承”。Solidity 中有四种函数可见性:
我们将在 Solana 中实现类似功能。
之前教程中定义的所有函数默认是公共的:
pub fn my_public_function(ctx: Context<Initialize>) -> Result<()> {
Ok(())
}
使用 pub 关键字标记函数为公共。在 #[program] 模块内,所有函数必须声明为 pub,否则无法编译。
在 Solana 中,程序内部调用自身公共函数并不常见。因此,pub 函数更接近 Solidity 的 external 函数。若需在程序内部调用,建议将逻辑封装为私有函数,再由公共函数调用。
虽然 #[program] 模块内的函数必须是 pub,但文件或模块级别可以定义非 pub 函数。示例:
use anchor_lang::prelude::*;
declare_id!("F26bvRaY1ut3TD1NhrXMsKHpssxF2PAUQ7SjZtnrLkaM");
#[program]
pub mod func_test {
use super::*;
pub fn initialize(ctx: Context<Initialize>) -> Result<()> {
let u = get_a_num(); // 调用私有函数
msg!("{}", u);
Ok(())
}
}
fn get_a_num() -> u64 { // 文件级私有函数
2
}
#[derive(Accounts)]
pub struct Initialize {}
说明:get_a_num 未使用 pub,仅在文件内可见。
Rust 不是面向对象语言,没有 Solidity 的“类”概念,可见性通过模块系统管理,详见 Rust 文档 - 可见性与隐私。
内部函数在模块及其子模块或导入它的模块中可见:
use anchor_lang::prelude::*;
declare_id!("53hgft52DHUKMPHGu1kusuwxFGk2T8qngwSw2SyGRNrX");
#[program]
pub mod func_visibility {
use super::*;
pub fn initialize(_ctx: Context<Initialize>) -> Result<()> {
some_internal_function::internal_function(); // 调用内部函数
Ok(())
}
pub mod some_internal_function {
pub fn internal_function() { // 模块内公开
// 内部逻辑
}
}
}
mod do_something {
use crate::func_visibility;
pub fn some_func_here() {
func_visibility::some_internal_function::internal_function(); // 外部访问
}
}
#[derive(Accounts)]
pub struct Initialize {}
验证:检查 ./target/idl/func_visibility.json,internal_function 未出现在 IDL 中,表明它未暴露给外部调用,仅限程序内部使用。
私有函数仅在定义它的模块内可见,使用 pub(in path) 限制范围:
use anchor_lang::prelude::*;
declare_id!("53hgft52DHUKMPHGu1kusuwxFGk2T8qngwSw2SyGRNrX");
#[program]
pub mod func_visibility {
use super::*;
pub fn initialize(_ctx: Context<Initialize>) -> Result<()> {
some_private_function::private_function(); // 模块内调用
Ok(())
}
pub mod some_private_function {
pub(in crate::func_visibility) fn private_function() { // 限制为父模块可见
// 私有逻辑
}
}
}
#[derive(Accounts)]
pub struct Initialize {}
尝试从外部调用:
mod do_something {
use crate::func_visibility;
pub fn some_func_here() {
func_visibility::some_private_function::private_function(); // 编译失败
}
}
报错:error[E0603]: function private_function
is private,表明 private_function 仅限 func_visibility 模块内部访问。
Rust 没有类的继承,但在 Solana 中可通过模块复用类似功能。
在 src/calculate.rs 中定义:
pub fn add(x: u64, y: u64) -> u64 {
x + y
}
在 src/lib.rs 中使用:
use anchor_lang::prelude::*;
pub mod calculate; // 导入模块
declare_id!("53hgft52DHUKMPHGu1kusuwxFGk2T8qngwSw2SyGRNrX");
#[program]
pub mod func_visibility {
use super::*;
pub fn add_two_numbers(_ctx: Context<Initialize>, x: u64, y: u64) -> Result<()> {
let result = calculate::add(x, y);
msg!("{} + {} = {}", x, y, result);
Ok(())
}
}
#[derive(Accounts)]
pub struct Initialize {}
也可以在 lib.rs 内定义模块:
use anchor_lang::prelude::*;
declare_id!("53hgft52DHUKMPHGu1kusuwxFGk2T8qngwSw2SyGRNrX");
#[program]
pub mod func_visibility {
use super::*;
pub fn add_two_numbers(_ctx: Context<Initialize>, x: u64, y: u64) -> Result<()> {
let result = calculate::add(x, y);
msg!("{} + {} = {}", x, y, result);
Ok(())
}
}
mod calculate {
pub fn add(x: u64, y: u64) -> u64 {
x + y
}
}
#[derive(Accounts)]
pub struct Initialize {}
注意:add 必须标记为 pub,否则无法从 func_visibility 调用。
Rust 和 Solana 中的可见性与 Solidity 不同:
Solidity 通过类实现继承,而 Rust 使用模块组织代码。通过导入模块,可复用功能,模拟继承效果。
【笔记配套代码】 https://github.com/0xE1337/rareskills_evm_to_solana 【参考资料】 https://learnblockchain.cn/column/119 https://www.rareskills.io/solana-tutorial
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!