Rust 与 Solana 中的可见性及模块化复用

  • 0xE
  • 发布于 3天前
  • 阅读 328

本文将探讨如何在 Rust 和 Solana 中实现类似 Solidity 的函数可见性,以及如何通过模块化复用来模拟“继承”。

本文将探讨如何在 Rust 和 Solana 中实现类似 Solidity 的函数可见性,以及如何通过模块化复用来模拟“继承”。Solidity 中有四种函数可见性:

  • public:合约内外均可访问。
  • external:仅限合约外部访问。
  • internal:合约内部及继承合约可访问。
  • private:仅限合约内部访问。

我们将在 Solana 中实现类似功能。


公共函数

之前教程中定义的所有函数默认是公共的:

pub fn my_public_function(ctx: Context<Initialize>) -> Result<()> {
    Ok(())
}

使用 pub 关键字标记函数为公共。在 #[program] 模块内,所有函数必须声明为 pub,否则无法编译。


无需区分 public 与 external

在 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 不同:

  • 公共函数:使用 pub,在 #[program] 内必须公开,类似 Solidity 的 external。
  • 内部函数:通过嵌套模块实现,未暴露于 IDL,可在程序内跨模块访问。
  • 私有函数:使用 pub(in path) 限制,仅在指定模块内可见。

Solidity 通过类实现继承,而 Rust 使用模块组织代码。通过导入模块,可复用功能,模拟继承效果。


【笔记配套代码】 https://github.com/0xE1337/rareskills_evm_to_solana 【参考资料】 https://learnblockchain.cn/column/119 https://www.rareskills.io/solana-tutorial

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
0xE
0xE
0x59f6...a17e
17年进入币圈,Web3 开发者。刨根问底探链上真相,品味坎坷悟 Web3 人生。