Rust:重构后结构的可见性现已公开;无法将main添加到发布(在板条箱::main中)

Rust:重构后结构的可见性现已公开;无法将main添加到发布(在板条箱::main中),rust,visibility,Rust,Visibility,我对锈菌还比较陌生,因此以下可能也是对一个概念的误解: 我从中获取了ggez基本项目模板,如下所示: use ggez::{graphics, Context, ContextBuilder, GameResult}; use ggez::event::{self, EventHandler}; fn main() { // Make a Context. let (mut ctx, mut event_loop) = ContextBuilder::new("my_

我对锈菌还比较陌生,因此以下可能也是对一个概念的误解: 我从中获取了ggez基本项目模板,如下所示:

use ggez::{graphics, Context, ContextBuilder, GameResult};
use ggez::event::{self, EventHandler};

fn main() {
    // Make a Context.
    let (mut ctx, mut event_loop) = ContextBuilder::new("my_game", "Cool Game Author")
        .build()
        .expect("aieee, could not create ggez context!");

    // Create an instance of your event handler.
    // Usually, you should provide it with the Context object to
    // use when setting your game up.
    let mut my_game = MyGame::new(&mut ctx);

    // Run!
    match event::run(&mut ctx, &mut event_loop, &mut my_game) {
        Ok(_) => println!("Exited cleanly."),
        Err(e) => println!("Error occured: {}", e)
    }
}

struct MyGame {
    // Your state here...
}

impl MyGame {
    pub fn new(_ctx: &mut Context) -> MyGame {
        // Load/create resources such as images here.
        MyGame {
            // ...
        }
    }
}

impl EventHandler for MyGame {
    fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
        // Update code here...
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx, graphics::WHITE);
        // Draw code here...
        graphics::present(ctx)
    }
}
src
|---main.rs
|---game
    |---mod.rs
    |---game.rs
    |---init.rs
并将其添加到
game.rs

use ggez::event::EventHandler;
use ggez::{Context, GameResult, graphics};
只要我把
MyGame
公之于众,一切都能正常工作

然而,现在重构正在发生巨大的变化,因为MyGame以前是私有的。 我用
pub(在infinite_runner::main中)
和类似的方法尝试了几种方法,比如
cratet::main
,但没有一种方法被各种错误消息接受


现在我的问题是,有没有一种方法可以将
MyGame
公开给
main.rs
而不向任何其他人公开?main似乎不是一个有效的目标。

我通过在rust文档中反复强调,设法找到了它。 虽然回答我自己的问题有点可疑,但实际上可能对其他人有所帮助:

TLDR; 我们希望主函数内的代码可以访问MyGame,但外部的任何其他模块都被拒绝访问

是否可以将代码分解到
游戏中。rs
:否

能做到吗?是的

以下是原因和方式:

根据防锈文件:

由于物品可以是公共的,也可以是私人的,所以生锈是允许的 两种情况下的项目访问:

  • 如果一个项目是公共的,那么它可以从一些外部访问 模块m如果您可以从m访问项目的所有父模块。你 还可以通过再出口为项目命名。看见 下面
  • 如果项目是私有的,则当前模块可以访问该项目 以及它的后代
  • 这意味着我不能在水平方向上进行分解,同时期望水平方向上进行限制。由于
    main.rs
    位于顶层,因此整个板条箱可以访问与任何其他模块相同级别的任何公共内容,因为每个模块都可以访问顶层的父模块。 因此,重构到同一级别的文件(模块)的答案是:否

    另一方面,如果我将代码分解成一个名为
    lib.rs
    的文件,那么唯一的区别就是路径,因为顶层的
    lib.rs
    隐式地只是
    crater
    路径,而在名为
    game.rs
    的文件中,路径将是
    crater::game

    但是,通过垂直分解,可以实现与单个文件相同的行为。我们创建一个名为
    game
    的目录,并将
    game.rs
    移动到此目录中,并将pub关键字添加到MyGame:
    pub struct MyGame
    。 类似于python
    \uuuu init\uuuuupy.py
    文件,rust需要一个文件
    mod.rs
    ,以使目录成为一个模块。 在
    mod.rs
    中,您声明了您拥有的文件,在本例中,
    mod game
    。 现在我们可以通过路径
    crater::game::game::MyGame
    来解决MyGame,但是由于
    game.rs
    被声明为私有,因此对MyGame的访问是密封的,因为路径的所有元素都必须是公共的。 但是,由于MyGame是公开的,所以同一级别的任何模块都可以访问它。 我们不能将
    main.rs
    移动到游戏目录中,但我们可以将其中的代码分解到另一个函数中。让我们称之为
    init
    ,因为缺乏幻想。我们将init函数放在游戏目录中名为
    init.rs
    的文件中,并在
    mod.rs
    中声明为public,如下所示:
    pub mod init
    。 现在我们可以调用
    game::init::init()
    ,因为它是公共的,但不是
    game::game::MyGame
    。但是,Init可以访问
    MyGame

    最终结构如下所示:

    use ggez::{graphics, Context, ContextBuilder, GameResult};
    use ggez::event::{self, EventHandler};
    
    fn main() {
        // Make a Context.
        let (mut ctx, mut event_loop) = ContextBuilder::new("my_game", "Cool Game Author")
            .build()
            .expect("aieee, could not create ggez context!");
    
        // Create an instance of your event handler.
        // Usually, you should provide it with the Context object to
        // use when setting your game up.
        let mut my_game = MyGame::new(&mut ctx);
    
        // Run!
        match event::run(&mut ctx, &mut event_loop, &mut my_game) {
            Ok(_) => println!("Exited cleanly."),
            Err(e) => println!("Error occured: {}", e)
        }
    }
    
    struct MyGame {
        // Your state here...
    }
    
    impl MyGame {
        pub fn new(_ctx: &mut Context) -> MyGame {
            // Load/create resources such as images here.
            MyGame {
                // ...
            }
        }
    }
    
    impl EventHandler for MyGame {
        fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
            // Update code here...
            Ok(())
        }
    
        fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
            graphics::clear(ctx, graphics::WHITE);
            // Draw code here...
            graphics::present(ctx)
        }
    }
    
    src
    |---main.rs
    |---game
        |---mod.rs
        |---game.rs
        |---init.rs
    
    main.rs:

    mod game;
    use game::init;
    
    fn main() {
        init::init();
    }
    
    国防部:

    pub mod init;
    mod game;
    
    game.rs:

    use ggez::event::EventHandler;
    use ggez::{graphics, Context, GameResult};
    
    pub struct MyGame {
        // Your state here...
    }
    
    impl MyGame {
        pub fn new(_ctx: &mut Context) -> MyGame {
            // Load/create resources such as images here.
            MyGame {
                // ...
            }
        }
    }
    
    impl EventHandler for MyGame {
        fn update(&mut self, _ctx: &mut Context) -> GameResult<()> {
            // Update code here...
            Ok(())
        }
    
        fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
            graphics::clear(ctx, graphics::WHITE);
            // Draw code here...
            graphics::present(ctx)
        }
    }
    

    我想说,这是一个普遍的做法,一个板条箱的模块有更多的访问,他们需要。因此,我不认为pub struct MyGame有问题。我不确定这是否没有问题,因为该结构不仅暴露在板条箱内部,而且暴露在任何其他模块之外。如果MyGame是某种实现细节(这就是为什么它最初是私有的),那么我现在已经向外界公开了这个实现细节,这肯定不是我想要的。我假设
    pub(in)
    是为了解决这个问题,但是我不知道如何将
    main.rs
    文件作为目标。pub(claiter)struct MyGame对你有用吗?@Kitsu谢谢你的帮助。这将编译结构,但也将结构暴露给板条箱内外的任何其他模块。然而,我们想要的是将我的游戏与我的主函数中的代码之外的任何东西隔离开来。请参阅我的答案,以获取解决此问题的方法。